Необязательные параметры? - PullRequest
371 голосов
/ 09 января 2010

Может ли Go иметь дополнительные параметры? Или я могу просто определить две функции с одинаковым именем и разным количеством аргументов?

Ответы [ 10 ]

363 голосов
/ 09 января 2010

Go не имеет необязательных параметров и не поддерживает перегрузку методов :

Способ отправки упрощен, если он не нужно делать сопоставление типов как Что ж. Опыт работы с другими языками сказал нам, что, имея различные методы с тем же именем, но разные подписи были изредка полезно, но это также может быть запутанный и хрупкий на практике. Соответствует только по имени и требует согласованность типов была основной упрощающее решение в виде Го система.

177 голосов
/ 06 ноября 2013

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

func foo(params ...int) {
    fmt.Println(len(params))
}

func main() {
    foo()
    foo(1)
    foo(1,2,3)
}
139 голосов
/ 28 ноября 2012

Вы можете использовать структуру, которая включает параметры:

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})
101 голосов
/ 12 октября 2014

Для произвольного, потенциально большого количества необязательных параметров, хорошая идиома - использовать Функциональные опции .

Для вашего типа 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 может расти со временем, не нарушая существующий код, поскольку сигнатура конструктора остается неизменной, когда требуются новые опции.
  • позволяет использовать вариант использования по умолчанию как самый простой: никаких аргументов вообще!
  • обеспечивает точный контроль инициализации сложных значений.

Эта техника была придумана Робом Пайком , а также продемонстрирована Дейвом Чейни .

16 голосов
/ 09 января 2010

Ни дополнительные параметры, ни перегрузка функций не поддерживаются в Go. Go поддерживает переменное число параметров: Передача аргументов ... параметрам

5 голосов
/ 09 января 2010

Нет - ни то, ни другое. Согласно Go для программистов на C ++ документы,

Go не поддерживает функцию перегрузка и не поддерживает пользователя определенные операторы.

Я не могу найти столь же ясное утверждение, что необязательные параметры не поддерживаются, но они также не поддерживаются.

4 голосов
/ 17 ноября 2016

Вы можете довольно красиво описать это в функции, аналогичной приведенной ниже.

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 ->
2 голосов
/ 07 февраля 2018

Язык Go не поддерживает перегрузку методов, но вы можете использовать переменные аргументы, как необязательные параметры, также вы можете использовать интерфейс {} в качестве параметра, но это не лучший выбор.

2 голосов
/ 11 августа 2016

В итоге я использовал комбинацию структуры params и variadic args. Таким образом, мне не пришлось менять существующий интерфейс, который использовался несколькими сервисами, и мой сервис мог передавать дополнительные параметры по мере необходимости. Пример кода на детской площадке Голанга: https://play.golang.org/p/G668FA97Nu

1 голос
/ 20 августа 2017

Я немного опоздал, но если вам нравится свободный интерфейс, вы можете создать сеттеры для цепных вызовов следующим образом:

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, и имеет те же преимущества, но имеет некоторые недостатки:

  1. Если возникает ошибка, она не будет немедленно прервана, поэтому она будет несколько менее эффективной, если вы ожидаете, что ваш конструктор будет часто сообщать об ошибках.
  2. Вам придется потратить строку, объявляющую переменную err и обнуляющую ее.

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

...