Em Go, uma função só pode aceitar argumentos dos tipos especificados na lista de parâmetros na definição da função. O recurso de linguagem de parâmetro variável complica um pouco isso, mas segue regras bem definidas.
A assinatura da função para fmt.Printlné:
func Println(a ...interface{}) (n int, err error)
De acordo com a especificação do idioma ,
O parâmetro de entrada final em uma assinatura de função pode ter um tipo prefixado com .... Uma função com tal parâmetro é chamada de variadic e pode ser chamada com zero ou mais argumentos para aquele parâmetro.
Isso significa que você pode passar Printlnuma lista de argumentos do interface{}tipo. Já que todos os tipos implementam a interface vazia, você pode passar uma lista de argumentos de qualquer tipo, que é como você pode chamar Println(1, "one", true), por exemplo, sem erros. Consulte a seção "Passando argumentos para ... parâmetros" da especificação do idioma:
o valor passado é uma nova fatia do tipo [] T com uma nova matriz subjacente cujos elementos sucessivos são os argumentos reais, que devem ser atribuídos a T.
A parte que está causando problemas está logo depois na especificação:
Se o argumento final puder ser atribuído a uma fatia do tipo [] T, ele pode ser passado inalterado como o valor para um parâmetro ... T se o argumento for seguido por .... Neste caso, nenhuma nova fatia é criada.
flag.Args()é tipo []string. Já que Tem Printlné interface{}, []Té []interface{}. Portanto, a questão se resume a se um valor de fatia de string pode ser atribuído a uma variável do tipo de fatia de interface. Você pode testar isso facilmente em seu código go tentando uma atribuição, por exemplo:
s := []string{}
var i []interface{}
i = s
Se você tentar essa atribuição, o compilador produzirá esta mensagem de erro:
cannot use s (type []string) as type []interface {} in assignment
E é por isso que você não pode usar as reticências após uma fatia de string como um argumento para fmt.Println. Não é um bug, está funcionando conforme o esperado.
Há muitas ainda de maneiras que você pode imprimir flag.Args()com Println, tais como
fmt.Println(flag.Args())
(que sairá como [elem0 elem1 ...], por documentação do pacote fmt )
ou
fmt.Println(strings.Join(flag.Args(), ` `)
(que produzirá os elementos de fatia de string, cada um separado por um único espaço) usando a função Join no pacote de strings com um separador de string, por exemplo.
go run test.go some test flags), e parecia funcionar ao mudarflags.Args()...para apenasflag.Args()(a saída é[some test flags], seguida pela nova linha; também parecia funcionar com o registro de sinalizadores reais). Não vou fingir que entendi o porquê, e a resposta de Stephen é muito mais informativa de qualquer maneira :)