Является ли вариационная функция подходящим решением для необязательного аргумента?

Если у меня есть функция, в которой последний аргумент является необязательным, целесообразно ли использовать ..., чтобы аргумент был необязательным, или это считается дурным тоном?

Пример:

func Foo(s ...string) {
    switch len(s) {
        case 0:
            fmt.Println("You didn't pass an argument")
        case 1:
            fallthrough
        default:
            fmt.Printf("You passed %s\n", s[0])
    }
}

Foo("bar")        // "You passed bar"
Foo()             // "You didn't pass an argument"
Foo("bar", "baz") // "You passed bar"

В этом примере меня не волнует, передается ли слишком много аргументов, но я могу справиться с этим в случае default:, когда это необходимо.


person I Hate Lazy    schedule 22.09.2012    source источник


Ответы (3)


Я бы не рекомендовал это. Существуют разные проблемы с (ab) использованием переменных параметров для передачи необязательных аргументов. Наиболее важным из них, вероятно, является то, что форма последнего arg ...T) допускает только один тип. Для более чем одного необязательного параметра с более чем одним типом можно использовать ...interface{}, но это влечет за собой ненужные затраты времени выполнения (un)boxing и отсутствие какой-либо (полезной) проверки типа во время компиляции.

Другой возможный аргумент против заключается в том, что я не думаю, что вы найдете пример/прецедент для этого где-либо в стандартной библиотеке, которую некоторые считают неофициальным руководством по стилю кодирования Go.

person zzzz    schedule 22.09.2012
comment
Что касается вашего первого абзаца, я понимаю, что вы говорите, но в моем случае я не искал динамическую типизацию. Его тип будет статическим, но его включение в вызов будет необязательным. Но ваш второй абзац полностью совпадает с тем, о чем я думал. Я оставлю вопрос на некоторое время, но пока +1. - person I Hate Lazy; 22.09.2012
comment
Ваш ответ и другой были очень хорошими, но ваш конкретно касался вопроса о подходящем стиле кодирования, предоставляя стандартную библиотеку в качестве соответствующего стандарта. Спасибо большое. - person I Hate Lazy; 27.09.2012

Если вам действительно нужны необязательные аргументы (а, как видно из стандартной библиотеки Go, это редкость), идиоматический способ — определить структуру с полями для каждого из необязательных аргументов, и тогда вызывающие могут передать структурный литерал с полями, которые они хотят заполнить.

Более распространенным является предоставление альтернативных функций или методов, когда это только один или два «необязательных» аргумента, которые должны быть в большинстве случаев.

Необязательные аргументы в таких языках, как Python, часто означают, что API растет и растет, пока у функций и методов не будет больше аргументов, чем кто-либо может вспомнить, и никогда не ясно, как взаимодействуют различные комбинации аргументов (и они еще менее проверены).

Принуждение вас к определению явных функций и методов для различных комбинаций параметров требует более тщательного обдумывания вашего API, но делает его более удобным в использовании и сопровождении в долгосрочной перспективе.

person uriel    schedule 23.09.2012

Все зависит от требований вашего проекта, если ваш проект находится в такой ситуации, то нет ничего плохого.

Необязательный аргумент предоставляется только для такого рода ситуаций.

person Ravindra Bagale    schedule 22.09.2012
comment
Просто это не совсем необязательный аргумент. Это средство вариативной функции, используемое для подделки необязательных аргументов. Побочным эффектом является неспособность компилятора проверить слишком много аргументов. Не был уверен, считается ли это хорошим тоном или это общепринятая практика. - person I Hate Lazy; 22.09.2012