Can Go имеют необязательные параметры? Или я могу просто определить две функции с тем же именем и другим числом аргументов?
Дополнительные параметры?
Ответ 1
Go не имеет необязательных параметров и не поддерживает перегрузку метода:
Отправка метода упрощается, если он не нужно выполнять сопоставление типов, как Что ж. Опыт работы на других языках сказал, что с методы с тем же именем, но иногда были разные подписи полезно, но также может быть путают и хрупки на практике. Соответствие только по названию и требование согласованность в типах была крупной упрощение решения в стиле Go система.
Ответ 2
Вы можете использовать структуру, которая включает в себя параметры:
type Params struct {
a, b, c int
}
func doIt(p Params) int {
return p.a + p.b + p.c
}
// you can call it without specifying all parameters
doIt(Params{a: 1, c: 9})
Ответ 3
Хорошим способом достижения чего-то вроде необязательных параметров является использование переменных переменных. Функция фактически получает срез любого типа, который вы указываете.
func foo(params ...int) {
fmt.Println(len(params))
}
func main() {
foo()
foo(1)
foo(1,2,3)
}
Ответ 4
Для произвольного, потенциально большого количества необязательных параметров, хорошая идиома заключается в использовании Функциональных опций.
Для вашего типа Foobar
сначала напишите только один конструктор:
func NewFoobar(options ...func(*Foobar) error) (*Foobar, error){
fb := &Foobar{}
// ... (write initializations with default values)...
for _, op := range options{
err := op(fb)
if err != nil {
return nil, err
}
}
return fb, nil
}
где каждый параметр является функцией, которая мутирует Foobar. Затем предоставите удобные способы для использования пользователем или создания стандартных параметров, например:
func OptionReadonlyFlag(fb *Foobar) error {
fb.mutable = false
return nil
}
func OptionTemperature(t Celsius) func(*Foobar) error {
return func(fb *Foobar) error {
fb.temperature = t
return nil
}
}
Для краткости вы можете указать имя типа параметров (Игровая площадка):
type OptionFoobar func(*Foobar) error
Если вам нужны обязательные параметры, добавьте их в качестве первых аргументов конструктора перед переменным options
.
Основными преимуществами идиомы функциональных опций являются:
- ваш API может расти со временем, не нарушая существующий код, потому что подпись constuctor остается прежней, когда нужны новые параметры.
- он позволяет использовать прецедент по умолчанию как самый простой: никаких аргументов вообще!
- он обеспечивает точное управление инициализацией сложных значений.
Эта техника была придумана Rob Pike, а также продемонстрирована Дейв Чейни.
Ответ 5
В Go не поддерживаются ни дополнительные параметры, ни перегрузка функций. Go поддерживает переменное количество параметров: Передача аргументов в... параметры
Ответ 6
Нет - нет. На Перейти для программистов на С++,
Go не поддерживает функцию перегрузка и не поддерживает пользователя определенных операторов.
Я не могу найти одинаково ясное утверждение о том, что необязательные параметры не поддерживаются, но они также не поддерживаются.
Ответ 7
Вы можете инкапсулировать это довольно хорошо в func, подобном тому, что ниже.
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
fmt.Println(prompt())
}
func prompt(params ...string) string {
prompt := ": "
if len(params) > 0 {
prompt = params[0]
}
reader := bufio.NewReader(os.Stdin)
fmt.Print(prompt)
text, _ := reader.ReadString('\n')
return text
}
В этом примере запрос по умолчанию имеет двоеточие и пробел перед ним.,.
:
., однако вы можете переопределить это, предоставив параметр функции приглашения.
prompt("Input here -> ")
Это приведет к следующему приглашению.
Input here ->
Ответ 8
В итоге я использовал комбинацию структуры params и variadic args. Таким образом, мне не пришлось менять существующий интерфейс, который был использован несколькими службами, и моя служба смогла передать дополнительные параметры по мере необходимости. Пример кода на игровой площадке golang: https://play.golang.org/p/G668FA97Nu
Ответ 9
Я немного опаздываю, но если вам нравится свободный интерфейс, вы можете создать свои сеттеры для таких цепочек:
type myType struct {
s string
a, b int
}
func New(s string, err *error) *myType {
if s == "" {
*err = errors.New(
"Mandatory argument `s` must not be empty!")
}
return &myType{s: s}
}
func (this *myType) setA (a int, err *error) *myType {
if *err == nil {
if a == 42 {
*err = errors.New("42 is not the answer!")
} else {
this.a = a
}
}
return this
}
func (this *myType) setB (b int, _ *error) *myType {
this.b = b
return this
}
И затем назовите его следующим образом:
func main() {
var err error = nil
instance :=
New("hello", &err).
setA(1, &err).
setB(2, &err)
if err != nil {
fmt.Println("Failed: ", err)
} else {
fmt.Println(instance)
}
}
Это похоже на Идиомы функциональных опций, представленные в ответе @Ripounet, и пользуется теми же преимуществами, но имеет некоторые недостатки:
- Если произошла ошибка, она не будет отменена немедленно, поэтому она будет немного менее эффективной, если вы ожидаете, что ваш конструктор будет часто сообщать об ошибках.
- Вам придется потратить строку, объявляющую переменную
err
и обнуляющую ее.
Существует, однако, небольшое преимущество, этот тип вызовов функций должен быть проще для встроенного компилятора, но я действительно не специалист.