Значення за замовчуванням у методі Go


100

Чи є спосіб вказати значення за замовчуванням у функції Go? Я намагаюся знайти це в документації, але не можу знайти нічого, що вказує на те, що це навіть можливо.

func SaySomething(i string = "Hello")(string){
...
}

Відповіді:



119

НІ, але є деякі інші варіанти реалізації значення за замовчуванням. Є кілька хороших дописів у блозі на цю тему, але ось деякі конкретні приклади.


** Варіант 1: ** Абонент вирішує використовувати значення за замовчуванням
// Both parameters are optional, use empty string for default value
func Concat1(a string, b int) string {
  if a == "" {
    a = "default-a"
  }
  if b == 0 {
    b = 5
  }

  return fmt.Sprintf("%s%d", a, b)
}

** Варіант 2: ** В кінці один необов’язковий параметр
// a is required, b is optional.
// Only the first value in b_optional will be used.
func Concat2(a string, b_optional ...int) string {
  b := 5
  if len(b_optional) > 0 {
    b = b_optional[0]
  }

  return fmt.Sprintf("%s%d", a, b)
}

** Варіант 3: ** Конфігураційна структура
// A declarative default value syntax
// Empty values will be replaced with defaults
type Parameters struct {
  A string `default:"default-a"` // this only works with strings
  B string // default is 5
}

func Concat3(prm Parameters) string {
  typ := reflect.TypeOf(prm)

  if prm.A == "" {
    f, _ := typ.FieldByName("A")
    prm.A = f.Tag.Get("default")
  }

  if prm.B == 0 {
    prm.B = 5
  }

  return fmt.Sprintf("%s%d", prm.A, prm.B)
}

** Варіант 4: ** Повний варіадичний синтаксичний аналіз аргументів (стиль javascript)
func Concat4(args ...interface{}) string {
  a := "default-a"
  b := 5

  for _, arg := range args {
    switch t := arg.(type) {
      case string:
        a = t
      case int:
        b = t
      default:
        panic("Unknown argument")
    }
  }

  return fmt.Sprintf("%s%d", a, b)
}

92
Який біль. Мені б хотілося, щоб це було: func Concat1(a string = 'foo', b int = 10) string {як і в більшості інших сучасних мов ... Це скоротило б будь-який із наведених прикладів до одного рядка коду.
Ротареті

Чи маємо ми можливість писати дві різні функції і залишати абоненту чітко визначити, що вони очікують.
ProgramCpp

@ProgramCpp ні, golang не дозволяє перевантаження функції Чи має мова Go функцію / метод перевантаження?
Вусал

10

Ні, неможливо вказати значення за замовчуванням. Я вважаю, що це робиться навмисно, щоб підвищити читабельність, коштуючи трохи більше часу (і, сподіваємось, продуманого) на кінці письменника.

Я думаю, правильним підходом до того, щоб мати "за замовчуванням", є наявність нової функції, яка надає це значення за замовчуванням більш загальній функції. Отримавши це, ваш код стає зрозумілішим щодо ваших намірів. Наприклад:

func SaySomething(say string) {
    // All the complicated bits involved in saying something
}

func SayHello() {
    SaySomething("Hello")
}

З дуже невеликими зусиллями я створив функцію, яка виконує загальні речі, і повторно використав загальну функцію. Ви можете побачити це у багатьох бібліотеках, fmt.Printlnнаприклад, просто додає новий рядок до того, що робило fmt.Printб інакше. Однак, читаючи чийсь код, стає зрозуміло, що вони мають намір зробити за допомогою функції, яку вони викликають. Зі значеннями за замовчуванням я не буду знати, що має відбуватися, не переходячи до функції, щоб вказати, яке значення за замовчуванням є насправді.


Мені подобається і погоджуюся з цією відповіддю, але, блін, я все ще бажаю, щоб вони хоч мали тупий, але ідіоматичний спосіб зробити це.
Sam Gomena

12
Аргумент "просто додати іншу функцію" може призвести до вибуху методів, необхідних для роботи з кількома перестановками, вимагає тягаря прийняття рішення щодо значущих, виявлених і запам'ятовуваних імен для цих методів, а також додає навантаження на вивчення пакетів, які використовують більше методів проти менше. #jmtcw
MikeSchinkel
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.