Вопрос

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

Это было полезно?

Решение

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

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

Другие советы

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

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

func main() {
    foo()
    foo(1)
    foo(1,2,3)
}

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

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})

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

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

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

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

Нет ... ни то, ни другое.В соответствии с Выбирайте программистов на C ++ Документы,

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

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

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

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.

prompt("Input here -> ")

Это приведет к появлению запроса, подобного приведенному ниже.

Input here ->

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

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

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 переменная и обнуление ее.

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

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

Вы можете передавать произвольные именованные параметры вместе с картой.

type varArgs map[string]interface{}

func myFunc(args varArgs) {

    arg1 := "default" // optional default value
    if val, ok := args["arg1"]; ok {
        // value override or other action
        arg1 = val.(string) // runtime panic if wrong type
    }

    arg2 := 123 // optional default value
    if val, ok := args["arg2"]; ok {
        // value override or other action
        arg2 = val.(int) // runtime panic if wrong type
    }

    fmt.Println(arg1, arg2)
}

func Test_test() {
    myFunc(varArgs{"arg1": "value", "arg2": 1234})
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top