У Go функція може приймати лише аргументи тих типів, що вказані у списку параметрів у визначенні функції. Мова варіадичної мови параметрів трохи ускладнює, але вона дотримується чітко визначених правил.
Підпис функції для fmt.Println:
func Println(a ...interface{}) (n int, err error)
Відповідно до мовної специфікації ,
Кінцевий вхідний параметр у підписі функції може мати тип із префіксом .... Функція з таким параметром називається варіадичною і може бути викликана нулем або більше аргументів для цього параметра.
Це означає, що ви можете передати Printlnсписок аргументів interface{}типу. Оскільки всі типи реалізують порожній інтерфейс, ви можете передати список аргументів будь-якого типу, саме таким чином ви можете телефонувати Println(1, "one", true), наприклад, без помилок. Див. Розділ "Передача аргументів у ... параметри" специфікації мови:
передане значення - це новий зріз типу [] T з новим базовим масивом, послідовними елементами якого є фактичні аргументи, які всі мають бути призначені T.
Частина, яка доставляє вам проблеми, відразу після цього описується в специфікації:
Якщо кінцевий аргумент можна призначити типу зрізу [] T, він може бути переданий без змін як значення параметра ... T, якщо за аргументом слідує .... У цьому випадку новий зріз не створюється.
flag.Args()є типом []string. Оскільки Tв Printlnє interface{}, []Tє []interface{}. Тож питання зводиться до того, чи можна значення зрізу рядка присвоїти змінній типу інтерфейсного зрізу. Ви можете легко перевірити це у своєму go-коді, спробувавши призначення, наприклад:
s := []string{}
var i []interface{}
i = s
Якщо ви спробуєте таке призначення, компілятор видасть таке повідомлення про помилку:
cannot use s (type []string) as type []interface {} in assignment
І тому ви не можете використовувати еліпсис після фрагмента рядка як аргумент fmt.Println. Це не помилка, вона працює за призначенням.
Є ще багато способів , ви можете надрукувати flag.Args()з Println, наприклад,
fmt.Println(flag.Args())
(що видаватиметься [elem0 elem1 ...]відповідно до документації пакета fmt )
або
fmt.Println(strings.Join(flag.Args(), ` `)
(який буде виводити елементи фрагмента рядка, кожен розділений єдиним пробілом), використовуючи, наприклад, функцію Join у пакеті рядків із розділювачем рядків.
go run test.go some test flags), і, здавалося, це спрацювало при змініflags.Args()...на justflag.Args()(висновок[some test flags], а потім новий рядок; також, здавалося, працював з реєстрацією фактичних прапорів). Не вдаватиме, що розуміє, чому, і відповідь Стівена в будь-якому випадку є набагато інформативнішою :)