In Go, una funzione può accettare solo argomenti dei tipi specificati nell'elenco dei parametri nella definizione della funzione. La caratteristica del linguaggio dei parametri variadici complica un po 'la cosa, ma segue regole ben definite.
La firma della funzione per fmt.Printlnè:
func Println(a ...interface{}) (n int, err error)
Secondo la lingua specifica ,
Il parametro finale in entrata in una firma di funzione può avere un tipo con prefisso .... Una funzione con un tale parametro è chiamata variadic e può essere invocata con zero o più argomenti per quel parametro.
Ciò significa che puoi passare Printlnun elenco di argomenti di interface{}tipo. Poiché tutti i tipi implementano l'interfaccia vuota, puoi passare un elenco di argomenti di qualsiasi tipo, che è il modo in cui puoi chiamare Println(1, "one", true), ad esempio, senza errori. Consulta la sezione "Passaggio di argomenti a ... parametri" della specifica del linguaggio:
il valore passato è una nuova slice di tipo [] T con un nuovo array sottostante i cui elementi successivi sono gli argomenti effettivi, che devono essere tutti assegnabili a T.
La parte che ti dà problemi è subito dopo nelle specifiche:
Se l'argomento finale è assegnabile a un tipo di slice [] T, può essere passato invariato come valore per un parametro ... T se l'argomento è seguito da .... In questo caso non viene creata una nuova slice.
flag.Args()è il tipo []string. Dal momento Tin Printlnè interface{}, []Tè []interface{}. Quindi la domanda si riduce a se un valore di slice di stringa è assegnabile a una variabile di tipo slice di interfaccia. Puoi facilmente testarlo nel tuo codice go tentando un compito, ad esempio:
s := []string{}
var i []interface{}
i = s
Se si tenta una tale assegnazione, il compilatore emetterà questo messaggio di errore:
cannot use s (type []string) as type []interface {} in assignment
Ed è per questo che non puoi usare i puntini di sospensione dopo una sezione di stringa come argomento per fmt.Println . Non è un bug, funziona come previsto.
Ci sono un sacco di modi ancora è possibile stampare flag.Args()con Println, ad esempio
fmt.Println(flag.Args())
(che verrà restituito come [elem0 elem1 ...]da documentazione del pacchetto fmt )
o
fmt.Println(strings.Join(flag.Args(), ` `)
(che produrrà gli elementi slice di stringa, ciascuno separato da un singolo spazio) utilizzando la funzione Join nel pacchetto di stringhe con un separatore di stringa, ad esempio.
go run test.go some test flags), e sembrava funzionare quando si cambiaflags.Args()...in soloflag.Args()(l'output è[some test flags], seguito dalla nuova riga; sembrava funzionare anche con la registrazione dei flag effettivi). Non farò finta di capire perché, e la risposta di Stephen è comunque molto più istruttiva :)