Dalam Go, sebuah fungsi hanya dapat menerima argumen dari tipe yang ditentukan dalam daftar parameter dalam definisi fungsi. Fitur bahasa parameter variadic sedikit memperumitnya, tetapi mengikuti aturan yang ditentukan dengan baik.
Tanda tangan fungsi untuk fmt.Printlnadalah:
func Println(a ...interface{}) (n int, err error)
Sesuai dengan spesifikasi bahasa ,
Parameter masuk terakhir dalam tanda tangan fungsi mungkin memiliki tipe yang diawali dengan .... Fungsi dengan parameter seperti itu disebut variadic dan dapat dipanggil dengan nol atau lebih argumen untuk parameter itu.
Ini berarti Anda dapat memberikan Printlndaftar interface{}tipe argumen . Karena semua tipe mengimplementasikan antarmuka kosong, Anda bisa meneruskan daftar argumen tipe apa pun, begitulah cara Anda memanggil Println(1, "one", true), misalnya, tanpa kesalahan. Lihat bagian "Meneruskan argumen ke ... parameter" pada spesifikasi bahasa:
nilai yang diteruskan adalah potongan baru tipe [] T dengan larik dasar baru yang elemen-elemennya berurutan adalah argumen sebenarnya, yang semuanya harus dapat ditetapkan ke T.
Bagian yang memberi Anda masalah ada tepat setelah itu dalam spesifikasi:
Jika argumen terakhir dapat ditetapkan ke tipe slice [] T, argumen tersebut dapat dikirimkan tanpa perubahan sebagai nilai untuk parameter ... T jika argumen tersebut diikuti oleh .... Dalam kasus ini, tidak ada slice baru yang dibuat.
flag.Args()adalah tipe []string. Sejak Tdi Printlnadalah interface{}, []Tadalah []interface{}. Jadi pertanyaannya adalah apakah nilai potongan string dapat ditetapkan ke variabel jenis potongan antarmuka. Anda dapat dengan mudah mengujinya di kode go Anda dengan mencoba sebuah tugas, misalnya:
s := []string{}
var i []interface{}
i = s
Jika Anda mencoba melakukan tugas seperti itu, kompilator akan menampilkan pesan kesalahan ini:
cannot use s (type []string) as type []interface {} in assignment
Dan itulah mengapa Anda tidak dapat menggunakan elipsis setelah potongan string sebagai argumen untuk fmt.Println. Ini bukan bug, ini berfungsi sebagaimana mestinya.
Ada banyak masih dari cara Anda dapat mencetak flag.Args()dengan Println, seperti
fmt.Println(flag.Args())
(yang akan ditampilkan sebagai [elem0 elem1 ...], sesuai dokumentasi paket fmt )
atau
fmt.Println(strings.Join(flag.Args(), ` `)
(yang akan mengeluarkan elemen potongan string, masing-masing dipisahkan oleh satu spasi) menggunakan fungsi Gabung dalam paket string dengan pemisah string, misalnya.
go run test.go some test flags), dan tampaknya berfungsi ketika mengubahflags.Args()...menjadi hanyaflag.Args()(keluaran adalah[some test flags], diikuti oleh baris baru; juga tampaknya bekerja dengan mendaftarkan bendera yang sebenarnya). Tidak akan berpura-pura mengerti mengapa, dan jawaban Stephen jauh lebih informatif :)