Funciones variantes en Go

fade by clockbirds



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 Typeen un parámetro elem. En otras palabras, Go crea una variable elemcon 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 appendespera que el primer argumento sea un segmento de tipo Typeseguido de un número arbitrario de argumentos. Pero, ¿cómo se agrega una rebanada s2a una rebanada s1?



De la definición de la función, append()se deduce que no podemos pasarle dos porciones; Typesolo 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 s1y s2el 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 acceptcuá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 appendes 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 getMultiplescon un primer argumento de factortipo 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 makecrear un sector vacío, tiene el mismo tamaño que el sector args. Usando un bucle for range, multiplique los elementos de corte argspor 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óngetMultiplescomo segundo argumento? El compilador reportará un error: en el argumentogetMultiplesno se puede usars (type [] int)como tipoint. Esto se debe a que el segmento tiene un tipo del que[]int, getMultiplesespera 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 argso 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 originalshan 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:



  1. Go y cachés de CPU
  2. Por qué un desarrollador de backend debería aprender el lenguaje de programación Go
  3. Nuestro canal de telegramas sobre transformación digital



All Articles