Подтвердить что ты не робот

Как установить значения по умолчанию в структурах Go

Существует несколько ответов/методов для следующего вопроса:

  • Как установить значения по умолчанию для golang structs?
  • Как инициализировать структуры в golang

У меня есть несколько ответов, но требуется дальнейшее обсуждение.

4b9b3361

Ответ 1

  1. Вынудите метод получить структуру (путь конструктора).

    Хороший дизайн - сделать ваш тип неэкспортированным, но предоставьте экспортированную функцию конструктора, такую как NewMyType(), в которой вы можете правильно инициализировать вашу структуру/тип. Также возвращайте тип интерфейса, а не конкретный тип, и интерфейс должен содержать все, что другие хотят сделать с вашим значением. И ваш конкретный тип должен реализовывать этот интерфейс, конечно.

    Это можно сделать, просто сделав сам тип неэкспортированным. Вы можете экспортировать функцию NewSomething и даже поля Text и DefaultText, но просто не экспортируйте что-то типа структуры

  2. Другой способ настроить его для собственного модуля - использовать структуру Config для установки значений по умолчанию (опция 5 в ссылке). Однако это не очень хороший способ.

Ответ 2

Одна из возможных идей - написать отдельную функцию конструктора.

//Something is the structure we work with
type Something struct {
     Text string 
     DefaultText string 
} 
// NewSomething create new instance of Something
func NewSomething(text string) Something {
   something := Something{}
   something.Text = text
   something.DefaultText = "default text"
   return something
}

Ответ 3

Одна проблема с вариантом 1 в ответ от Виктор Заманян: если тип не экспортируется, то пользователи вашего пакета не могут объявить его как тип параметров функции и т.д. Один из способов - экспортировать интерфейс вместо структуры, например.

package candidate
// Exporting interface instead of struct
type Candidate interface {}
// Struct is not exported
type candidate struct {
    Name string
    Votes unit32 // Defaults to 0
}
// We are forced to call the constructor to get an instance of candidate
func New(name string) Candidate {
    return candidate{name, 0}  // enforce the default value here
}

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

Ответ 4

С https://golang.org/doc/effective_go.html#composite_literals:

Иногда нулевое значение недостаточно, и необходим инициализирующий конструктор, как в этом примере, полученном из пакета os.

    func NewFile(fd int, name string) *File {
      if fd < 0 {
        return nil
      }
      f := new(File)
      f.fd = fd
      f.name = name
      f.dirinfo = nil
      f.nepipe = 0
      return f
}

Ответ 5

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

Предположим, у вас есть следующая структура с 2 тегами по умолчанию default0 и default1.

type A struct {
   I int    'default0:"3" default1:"42"'
   S string 'default0:"Some String..." default1:"Some Other String..."'
}

Теперь можно установить значения по умолчанию.

func main() {

ptr := &A{}

Set(ptr, "default0")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=3 ptr.S=Some String...

Set(ptr, "default1")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=42 ptr.S=Some Other String...
}

Здесь полная программа на детской площадке.

Если вы заинтересованы в более сложном примере, скажем, с кусочками и картами, посмотрите на creasty/defaultse

Ответ 6

type Config struct {
    AWSRegion                               string 'default:"us-west-2"'
}