Tracks
/
Go
Go
/
Temario
/
Funciones
Fu

Funciones en Go

1 ejercicio

Acerca de Funciones

Una función te permite agrupar código en una unidad reutilizable. Consta de la palabra clave func, el nombre de la función y una lista separada por comas de cero o más parámetros y tipos entre paréntesis.

Parámetros de función

Todos los parámetros deben tener un tipo explícito; no hay inferencia de tipos para los parámetros. No hay valores predeterminados para los parámetros, por lo que todos los parámetros de función son obligatorios.

import "fmt"

// No parameters
func PrintHello() {
    fmt.Println("Hello")
}

// One parameter
func PrintHelloName(name string) {
  fmt.Println("Hello " + name)
}

Los parámetros del mismo tipo se pueden declarar juntos, seguidos de una única declaración de tipo.

import "fmt"

func PrintGreetingName(greeting, name string) {
  fmt.Println(greeting + " " + name)
}

Parámetros frente a argumentos

Vamos a repasar rápidamente dos términos que a menudo se confunden: parameters y arguments. Los parámetros de función son los nombres definidos en la firma de la función, como greeting y name en la función PrintGreetingName anterior. Los argumentos de función son los valores concretos que se pasan a los parámetros de la función cuando llamamos a la función. Por ejemplo, en el ejemplo de abajo, "Hello" y "Katrina" son los argumentos que se pasan a los parámetros greeting y name:

PrintGreetingName("Hello", "Katrina")

Valores devueltos

Los parámetros de la función van seguidos de cero o más valores devueltos, que también deben tener un tipo explícito. Los valores devueltos únicos se dejan sin paréntesis; los múltiples valores devueltos se envuelven entre paréntesis. Los valores se devuelven al código que llama desde las funciones mediante la palabra clave return. Puede haber varias instrucciones return en una función. La ejecución de la función termina en cuanto se encuentra con una de esas instrucciones return. Si se van a devolver varios valores desde una función, se separan por comas. Puedes encontrar más información sobre el uso idiomático de los múltiples valores devueltos en el concepto enlazado.

func Hello(name string) string {
  return "Hello " + name
}

func HelloAndGoodbye(name string) (string, string) {
  return "Hello " + name, "Goodbye " + name
}

Llamar a funciones

Para llamar a una función, se especifica el nombre de la función y se pasan argumentos para cada uno de sus parámetros entre paréntesis.

import "fmt"

// No parameters, no return value
func PrintHello() {
    fmt.Println("Hello")
}
// Called like this:
PrintHello()

// One parameter, one return value
func Hello(name string) string {
  return "Hello " + name
}
// Called like this:
greeting := Hello("Dave")

// Multiple parameters, multiple return values
func SumAndMultiply(a, b int) (int, int) {
    return a+b, a*b
}
// Called like this:
aplusb, atimesb := SumAndMultiply(a, b)

Valores devueltos con nombre y retorno desnudo

Además de los parámetros, los valores devueltos pueden tener nombre de forma opcional. Si se usan valores devueltos con nombre, una instrucción return sin argumentos devolverá esos valores. Esto se conoce como retorno «desnudo».

func SumAndMultiplyThenMinus(a, b, c int) (sum, mult int) {
    sum, mult = a+b, a*b
    sum -= c
    mult -= c
    return
}

Paso por valor frente a paso por referencia

También es importante aclarar el concepto de paso por valor y paso por referencia.

Primero, aclaremos el paso por valor. En el ejemplo de abajo, cuando pasamos la variable val a la función MultiplyByTwo, pasamos una copia de val. Por eso, newVal tiene el valor actualizado 4, pero la variable original val sigue siendo 2. Entre bastidores, Go esencialmente hace una copia del valor original para que solo esta copia, también conocida como v, sea modificada por la función.

val := 2
func MultiplyByTwo(v int) int {
    v = v * 2
    return v
}
newVal := MultiplyByTwo(val)
// newval is 4, val is still 2 because only a copy of its value was passed into the function

Estrictamente hablando, en Go todos los argumentos se pasan por valor, es decir, se hace una copia del valor o de los datos que se proporcionan a la función. Pero si no quieres hacer una copia de los datos que se pasan a una función y quieres cambiar los datos dentro de la función, entonces deberías usar pointers como argumentos, es decir, paso por referencia.

Punteros

Usamos un pointer para lograr el paso por referencia. Al pasar argumentos pointer a una función, podemos modificar los datos subyacentes que se pasan a la función en lugar de operar solo sobre una copia de los datos.

Por ahora, basta con saber que los tipos de puntero se reconocen por el * delante del tipo en la firma de la función.

func HandlePointers(x, y *int) {
    // Some logic to handle integer values referenced by pointers x and y
}

Si el concepto de pointer te resulta confuso, no te preocupes. Tenemos una sección específica más adelante en el temario para ayudarte a dominar los punteros.

Excepciones

Ten en cuenta que slices y maps son excepciones a la regla mencionada anteriormente. Cuando pasamos un slice o un map como argumentos a una función, se tratan como tipos de puntero aunque no haya un * explícito en el tipo. Esto significa que si pasamos un slice o un map a una función y modificamos sus datos subyacentes, los cambios se reflejarán en el slice o map originales.

Otros tipos de funciones

Las funciones en Go se consideran ciudadanos de primera clase, lo que las hace muy potentes. Hay otros conceptos relacionados con las funciones, como los métodos y las funciones anónimas, que conocerás más adelante en tu recorrido.

Editar en GitHub El enlace se abre en una nueva ventana o pestaña

Aprende Funciones