En Go, una función solo puede aceptar argumentos de los tipos especificados en la lista de parámetros en la definición de la función. La característica del lenguaje de parámetros variadic complica eso un poco, pero sigue reglas bien definidas.
La firma de la función fmt.Println
es:
func Println(a ...interface{}) (n int, err error)
Según la especificación del idioma ,
El parámetro entrante final en la firma de una función puede tener un tipo con el prefijo .... Una función con dicho parámetro se llama variadic y puede invocarse con cero o más argumentos para ese parámetro.
Esto significa que puede pasar Println
una lista de argumentos de interface{}
tipo. Dado que todos los tipos implementan la interfaz vacía, puede pasar una lista de argumentos de cualquier tipo, que es cómo puede llamar Println(1, "one", true)
, por ejemplo, sin error. Consulte la sección "Pasar argumentos a ... parámetros" de la especificación del idioma:
el valor pasado es un nuevo segmento de tipo [] T con una nueva matriz subyacente cuyos elementos sucesivos son los argumentos reales, todos los cuales deben ser asignables a T.
La parte que le está dando problemas está justo después de eso en la especificación:
Si el argumento final se puede asignar a un tipo de sector [] T, se puede pasar sin cambios como el valor de un parámetro ... T si el argumento va seguido de .... En este caso, no se crea un nuevo sector.
flag.Args()
es tipo []string
. Dado que T
en Println
es interface{}
, []T
es []interface{}
. Entonces, la pregunta se reduce a si un valor de segmento de cadena se puede asignar a una variable de tipo de segmento de interfaz. Puede probarlo fácilmente en su código de Go intentando una tarea, por ejemplo:
s := []string{}
var i []interface{}
i = s
Si intenta tal asignación, el compilador mostrará este mensaje de error:
cannot use s (type []string) as type []interface {} in assignment
Y es por eso que no puede usar la elipsis después de un segmento de cadena como argumento para fmt.Println
. No es un error, funciona según lo previsto.
Hay un montón de maneras aún se pueden imprimir flag.Args()
con Println
, como
fmt.Println(flag.Args())
(que saldrá como [elem0 elem1 ...]
, según la documentación del paquete fmt )
o
fmt.Println(strings.Join(flag.Args(), ` `)
(que generará la salida de los elementos de corte de cadena, cada uno separado por un espacio) usando la función Unir en el paquete de cadenas con un separador de cadena, por ejemplo.
go run test.go some test flags
), y parecía funcionar cuando cambiabaflags.Args()...
a soloflag.Args()
(la salida es[some test flags]
, seguida de la nueva línea; también parecía funcionar con el registro de banderas reales). No se pretende comprender por qué, y la respuesta de Stephen es de todos modos mucho más informativo :)