Funciones en GO (Golang)
En sí las funciones son bloques de código reutilizables, estas pueden o no tomar argumentos. Particularmente las funciones pueden devolver múltiples valores en su retorno.
En Go las funciones son declaradas con la palabra clave func
, también las podemos utilizar como métodos, pero eso lo veremos más adelante en este post.
func function_name([argument_1_name data_type, argument_n_name data_type])[return_data_type_1, return_data_type_n]{ //... }
La primera función con las que nos toparemos en nuestros proyectos es la función main, la función main es de donde empieza nuestro proyecto, por tanto, no posee argumentos.
main functionfunc main() { // code here }
Vemos unos ejemplos con argumentos y retornos, sobre los retornos se recomienda utilizar () cuando el hay más de un retorno y sin cuando es uno solo
function with multiple argumentsfunc suma(a int, b int) { suma := a + b fmt.Println("la suma de 1 + 2 es:", suma) }
Valores de Retorno
Como dijimos en el principio go nos permite múltiples valores de retorno, veremos poco a poco que podemos hacer con el retorno y sus distintas formas de utilizarlo.
Hagamos que la función anterior nos devuelva un resultado
function with returnfunc suma(a int, b int) int{ return a+b }
Ahora hagamos una función que devuelva 2 valores
function with multiple returnspackage main import ( "fmt" "math" ) func main() { result, mod := division(1.5, 2.4) fmt.Println("el resoltado es:", result) fmt.Println("el resto es:", mod) } func division(a float64, b float64) (float64, float64) { r := math.Mod(a, b) return a / b, r }
Valor de retorno nombrado
En go(golang) podemos nombrar las variables que retornara, esto puede ser muy ventajoso en algunas circunstancias, simplemente tenemos que asignarle un nombre tal como en los argumentos. En el momento del retorno simplemente llamaremos return
Para que vea un ejemplo de esto, cambiaremos el ejemplo anterior:
function with multiple returnspackage main import ( "fmt" "math" ) func main() { result, mod := division(1.5, 2.4) fmt.Println("el resoltado es:", result) fmt.Println("el resto es:", mod) } func division(a float64, b float64) (div float64,mod float64) { mod = math.Mod(a, b) div = a/b return }
el resoltado es: 0.625 el resto es: 1.5 Program exited.
Observemos bien lo que pasa, las variables div y mod ya fueron declaradas y, por tanto, no tendremos que hacer uso de :=
o var
dentro de func
. También podemos observar que toma los últimos valores de mod y div para el retorno.
defer
Hay en ocasiones en que es conveniente aplazar / retrasar la ejecución de una función esto lo podemos realizar con la palabra clave defer
delante de la función que deseamos aplazar su ejecución.
¿cuanto aplaza el hecho de usar defer?
Pues esta función que esté usando defer será ejecutada luego que todas las demás que la rodean sean ejecutadas.
Veamos el ejemplo original:
Ejemplo de deferpackage main import "fmt" func main() { defer fmt.Println("world") fmt.Println("hello") }
hello world Program exited.
¿Que sucede cuando hay mas de un defer? Bueno lo mejor es verlo en un ejemplo.
multiples defer examplepackage main import "fmt" func main() { defer fmt.Println("uno") defer fmt.Println("dos") defer fmt.Println("tres") defer fmt.Println("cuatro") if true{ defer fmt.Println("tres") } }
tres cuatro tres dos uno Program exited.
Es efectivo cuando tienes que liberar un recurso sin importar el retorno que nos dé la función
Métodos
Los métodos son algo distinto en go con respecto a otros lenguajes, en la mayoría de los lenguajes los métodos forman parte de una clase en go no existen las clases.
Los métodos los puede crear para cualquer named type, pero no para un puntero o una interfaz, es por ello que muchas veces vemos métodos creados para estructuras, pero tenga en cuenta que no necesariamente tienen que ser creados para ser utilizados con una estructura.
Un método se crea con la palabra clave func seguido de para que tipo nombrado(named type) es entre paréntesis, su nombre, argumentos y retorno
Sintaxisfunc (name type) method_name([arg1 arg1_type,.. argn type])[(return_type, .. return_type_n)]{ }
Por ejemplo:
El siguiente meto no ha sido creado para una estructuratype ByteSlice []byte func (slice ByteSlice) Append(data []byte) []byte { // Body exactly the same as the Append function defined above. }