Existem várias respostas / técnicas para a pergunta abaixo:
- Como definir valores padrão para estruturas golang?
- Como inicializar estruturas em golang
Tenho algumas respostas, mas é necessária mais discussão.
Existem várias respostas / técnicas para a pergunta abaixo:
Tenho algumas respostas, mas é necessária mais discussão.
Respostas:
Uma idéia possível é escrever uma função construtora separada
//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
}
NewSomething
e até os campos Text
e DefaultText
, mas não exporte o tipo de estrutura something
.
reflect.New()
, por exemplo), não se pode esperar que você saiba sobre sua função de fábrica com nome especial. Nesse caso, e menos que a própria linguagem seja alterada, acho que apenas uma interface (que a biblioteca poderia verificar) faria.
Forçar um método para obter a estrutura (a maneira do construtor).
Um bom design é tornar seu tipo não exportado, mas fornecer uma função construtora exportada como NewMyType () na qual você pode inicializar corretamente sua estrutura / tipo. Também retorne um tipo de interface e não um tipo concreto, e a interface deve conter tudo o que os outros desejam fazer com seu valor. E seu tipo concreto deve implementar essa interface, é claro.
Isso pode ser feito simplesmente tornando o tipo não importado. Você pode exportar a função NewSomething e até os campos Text e DefaultText, mas simplesmente não exporta o tipo de estrutura
Outra maneira de personalizá-lo para o seu próprio módulo é usar uma estrutura Config para definir valores padrão (Opção 5 no link) Não é uma boa maneira.
Um problema com a opção 1 na resposta de Victor Zamanian é que, se o tipo não for exportado, os usuários do seu pacote não poderão declará-lo como o tipo de parâmetros de função etc. Uma maneira de contornar isso seria exportar uma interface em vez de estrutura, por exemplo
package candidate
// Exporting interface instead of struct
type Candidate interface {}
// Struct is not exported
type candidate struct {
Name string
Votes uint32 // 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
}
O que nos permite declarar tipos de parâmetros de função usando a interface Candidate exportada. A única desvantagem que vejo desta solução é que todos os nossos métodos precisam ser declarados na definição da interface, mas você pode argumentar que isso é uma boa prática.
Votes unit32
provavelmente deve serVotes uint32
Existe uma maneira de fazer isso com as tags, que permitem vários padrões.
Suponha que você tenha a seguinte estrutura, com 2 tags padrão default0 e default1 .
type A struct {
I int `default0:"3" default1:"42"`
S string `default0:"Some String..." default1:"Some Other String..."`
}
Agora é possível definir os padrões.
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...
}
Aqui está o programa completo em um playground .
Se você estiver interessado em um exemplo mais complexo, digamos, com fatias e mapas, dê uma olhada em creasty / defaultse
Em https://golang.org/doc/effective_go.html#composite_literals :
Às vezes, o valor zero não é bom o suficiente e é necessário um construtor de inicialização, como neste exemplo, derivado do pacote 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
}
type Config struct {
AWSRegion string `default:"us-west-2"`
}