There are some equivalents of constructors for when the zero values can't make sensible default values or for when some parameter is necessary for the struct initialization.
Supposing you have a struct like this :
type Thing struct {
Name string
Num int
}
then, if the zero values aren't fitting, you would typically construct an instance with a NewThing function returning a pointer :
func NewThing(someParameter string) *Thing {
p := new(Thing)
p.Name = someParameter
p.Num = 33 // <- a very sensible default value
return p
}
When your struct is simple enough, you can use this condensed construct :
func NewThing(someParameter string) *Thing {
return &Thing{someParameter, 33}
}
If you don't want to return a pointer, then a practice is to call the function makeThing instead of NewThing :
func makeThing(name string) Thing {
return Thing{name, 33}
}
Reference : Allocation with new in Effective Go.
Answer from Denys Séguret on Stack OverflowThere are some equivalents of constructors for when the zero values can't make sensible default values or for when some parameter is necessary for the struct initialization.
Supposing you have a struct like this :
type Thing struct {
Name string
Num int
}
then, if the zero values aren't fitting, you would typically construct an instance with a NewThing function returning a pointer :
func NewThing(someParameter string) *Thing {
p := new(Thing)
p.Name = someParameter
p.Num = 33 // <- a very sensible default value
return p
}
When your struct is simple enough, you can use this condensed construct :
func NewThing(someParameter string) *Thing {
return &Thing{someParameter, 33}
}
If you don't want to return a pointer, then a practice is to call the function makeThing instead of NewThing :
func makeThing(name string) Thing {
return Thing{name, 33}
}
Reference : Allocation with new in Effective Go.
There are actually two accepted best practices:
- Make the zero value of your struct a sensible default. (While this looks strange to most people coming from "traditional" oop it often works and is really convenient).
- Provide a function
func New() YourTypor if you have several such types in your package functionsfunc NewYourType1() YourType1and so on.
Document if a zero value of your type is usable or not (in which case it has to be set up by one of the New... functions. (For the "traditionalist" oops: Someone who does not read the documentation won't be able to use your types properly, even if he cannot create objects in undefined states.)
Default struct constructors?
Struct Constructor
Why you should use dedicated constructors in Go
go - Golang struct construction generality - Stack Overflow
Videos
I'm wondering why go devs doesn't implement optional default constructors for structs. I.e. right now some structs can be created like this:
myStruct := MyStruct{}
But others require initialization, and must be created with factory functions:
anotherStruct := NewAnotherStruct()
So you never know which struct is safe to create dorectly and which require factory func.
With default constructor you would create all structs the same way, i.e.:
myStruct := MyStruct()
If default constructor is defined it is invoked to initialize the struct, it it is not defined then it is similar to MyStruct{}
The practice I've personally observed in Go (and it's also what's recommended in the effective Go or getting started with Go tutorials) is just to define a NewdbRepo function and use it for all instantation. It's implementation would look something like;
func NewdbRepo(f, b string) *dbRepo {
return &dbRepo{ foo:f, bar:b}
}
You can't actually define a constructor as you do in most C like languages so you just gotta provide a package scoped method to do construction for you. Also, if you're not using composite literals (the initilization style I use in my NewdbRepo implementation) then you may find that alone concise enough for your needs.
You can write one function with your initializing code:
func newDbRepo(foo, bar string) dbRepo {
// ...
}
Then you can use it with type conversion:
a := typeARepo(newDbRepo("foo", "bar"))
b := typeBRepo(newDbRepo("foo", "bar"))