El equipo de Mail.ru Cloud Solutions hatraducido un artículo sobre funciones variadas en Go. Su autor explica en qué se diferencian las funciones variadas de las funciones ordinarias y cómo crearlas.
¿Qué es una función variádica?
Función: un fragmento de código diseñado para realizar una tarea específica. A la función se le pasan uno o más argumentos y devuelve uno o más resultados.
Las funciones variantes son las mismas que las funciones regulares, pero pueden tomar un número infinito o variable de argumentos.
func f(elem ...Type)
Esta es una sintaxis típica de función variádica. El operador
...
, también conocido como operador de boxeo, le dice a Go que almacene todos los argumentos de tipo Type
en un parámetro elem
. En otras palabras, Go crea una variable elem
con un tipo []Type
, es decir, un segmento. Y todos los argumentos pasados a la función se almacenan en el segmento elem
.
Veamos un ejemplo de función
append()
.
append([]Type, args, arg2, argsN)
La función
append
espera que el primer argumento sea un segmento de tipo Type
seguido de un número arbitrario de argumentos. Pero, ¿cómo se agrega una rebanada s2
a una rebanada s1
?
De la definición de la función,
append()
se deduce que no podemos pasarle dos porciones; Type
solo hay un argumento de tipo . Por lo tanto, usamos el operador de unboxing ...
para descomprimir el segmento en una serie de argumentos. Luego se pueden pasar a la función append
.
append(s1, s2...)
...
denota tanto el operador de embalaje como el operador de desembalaje. El operador de unboxing siempre aparece después del nombre de la variable.
En nuestro ejemplo, las rodajas
s1
y s2
el mismo tipo. Por lo general, conocemos los parámetros de una función y la cantidad de argumentos que toma. ¿Cómo sabe una función accept
cuántos parámetros se le han pasado?
Si observa la declaración de la función
append
, puede ver la expresión elems ...Type
. Empaqueta todos los argumentos, comenzando por el segundo, en un segmento elems
.
func append(slice []Type, elems ...Type) []Type
Solo el último argumento en una declaración de función puede ser variable.
Por lo tanto, el primer argumento de la función
append
es solo un segmento, ya que se define como un segmento. Todos los argumentos posteriores se empaquetan en un argumento llamado elems
.
Ahora veamos cómo crear su propia función variada.
Cómo crear una función variada
Como se mencionó anteriormente, una función variada es una función regular que toma un número variable de argumentos. Para hacer esto, necesita usar el operador de boxeo
...Type
.
Escribamos una función
getMultiples
con un primer argumento de factor
tipo int
(factor de multiplicación) y un número variable de argumentos de tipo adicionales int
. Se empaquetarán en una rodaja args
.
Úselo para
make
crear un sector vacío, tiene el mismo tamaño que el sector args
. Usando un bucle for range
, multiplique los elementos de corte args
por factor
. Colocamos el resultado en un nuevo segmento vacío multiples
, que devolveremos como resultado de la función.
func getMultiples(factor int, args ...int) []int {
multiples := make([]int, len(args))
for index, val := range args {
multiples[index] = val * factor
}
return multiples
}
Esta es una función muy simple, aplícala dentro de un bloque
main()
.
func main() {
s := []int{10, 20, 30}
mult1 := getMultiples(2, s...)
mult2 := getMultiples(3, 1, 2, 3, 4)
fmt.Println(mult1)
fmt.Println(mult2)
}
https://play.go.org/p/BgU6H9orhrn
¿Qué sucede si, en el ejemplo anterior, pasa un segmento a una función
getMultiples
como segundo argumento? El compilador reportará un error: en el argumentogetMultiples
no se puede usars (type [] int)
como tipoint
. Esto se debe a que el segmento tiene un tipo del que[]int, getMultiples
espera parámetrosint
.
Cómo se pasa un segmento a una función variada
Slice es una referencia a una matriz. Entonces, ¿qué sucede cuando pasa una porción a una función variada usando el operador de unboxing? ¿Go crea un nuevo segmento
args
o utiliza un segmento antiguo s
?
Como no tenemos herramientas de comparación
args == s
, necesitamos cambiar el segmento args
. Luego averiguamos si el corte original ha cambiado s
.
https://play.go.org/p/fbNgVGu6JZO
En el ejemplo anterior, cambiamos ligeramente la función
getMultiples
. Y en lugar de crear un nuevo corte, asignamos los resultados del cálculo a los elementos del corte args
, reemplazando los elementos entrantes con los elementos multiplicados.
Como resultado, vemos que los valores del segmento original
s
han cambiado. Si pasa argumentos a la función variadic a través del operador de unboxing, Go usa referencias a la matriz de datos subyacente al original para crear un nuevo segmento. Tenga cuidado de no cometer un error, de lo contrario, los datos originales cambiarán como resultado de los cálculos.
¡Buena suerte!
Qué más leer: