How to set default values in Go structs
Solution 1
-
Force a method to get the struct (the constructor way).
From this post:
A good design is to make your type unexported, but provide an exported constructor function like
NewMyType()
in which you can properly initialize your struct / type. Also return an interface type and not a concrete type, and the interface should contain everything others want to do with your value. And your concrete type must implement that interface of course.This can be done by simply making the type itself unexported. You can export the function NewSomething and even the fields Text and DefaultText, but just don't export the struct type something.
-
Another way to customize it for you own module is by using a Config struct to set default values (Option 5 in the link). Not a good way though.
Solution 2
One possible idea is to write separate constructor function
//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
}
Solution 3
One problem with option 1 in answer from Victor Zamanian is that if the type isn't exported then users of your package can't declare it as the type for function parameters etc. One way around this would be to export an interface instead of the struct e.g.
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
}
Which lets us declare function parameter types using the exported Candidate interface. The only disadvantage I can see from this solution is that all our methods need to be declared in the interface definition, but you could argue that that is good practice anyway.
Solution 4
There is a way of doing this with tags, which allows for multiple defaults.
Assume you have the following struct, with 2 default tags default0 and default1.
type A struct {
I int `default0:"3" default1:"42"`
S string `default0:"Some String..." default1:"Some Other String..."`
}
Now it's possible to Set the defaults.
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...
}
Here's the complete program in a playground.
If you're interested in a more complex example, say with slices and maps, then, take a look at creasty/defaultse
Solution 5
From https://golang.org/doc/effective_go.html#composite_literals:
Sometimes the zero value isn't good enough and an initializing constructor is necessary, as in this example derived from package 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
}
Related videos on Youtube
Prateek
Java is an ocean and I want to explore all of its corners. Also interested in DIY & Productivity hacks that help in reducing the work/time taken. Learning my way through new technologies - Go, Node.js
Updated on January 20, 2022Comments
-
Prateek over 2 years
There are multiple answers/techniques to the below question:
- How to set default values to golang structs?
- How to initialize structs in golang
I have a couple of answers but further discussion is required.
-
icza about 8 years
-
Prateek about 8 years@icza You answer does give provide a way to do it but going by the Question Title, it is in no way similar or searchable since it is a very specific question. I will add the link in my answer though.
-
Duncan Jones almost 7 yearsThere are two questions here, pick one. Assuming you opt for the first question (as per question title), please be more specific about your prior research and where your other answers require more discusssion,.
-
Prateek about 8 yearsYes, this is one of the ways that I have also mentioned in my answer but there is no way we can force anyone to use this function only.
-
OneOfOne about 8 years@Prateek it's either this or use an interface, which would be ugly and overcomplicated.
-
Amit Kumar Gupta about 8 years@Prateek yes, you can force people to use this constructor if you simply make the type itself unexported. You can export the function
NewSomething
and even the fieldsText
andDefaultText
, but just don't export the struct typesomething
. -
Prateek about 8 yearsWorth Trying. Still wondering if the struct variable will be accessible directly. Will check it out. Thanks !!
-
Prateek about 8 years@Amit, I have mention an extension to this in my answer - which recommends to make use of interface as a return value
-
Victor Zamanian over 7 yearsThis is now a broken link (404): joneisen.tumblr.com/post/53695478114/golang-and-default-values
-
n8henrie about 7 yearsIt's available in the wayback machine.
-
decimus phostle over 6 yearsFWIW, I think it is 'Option 3' - at least in the wayback machine link. (There is no 'Option 5', there).
-
edam over 6 yearsThe problem is worse... if a third party (library, for example) is used to instantiate your struct (via
reflect.New()
, for example), it couldn't be expected to know about your specially-named factory function. In that case, and short of the language itself being changed, only an interface (which the library could check for) would do, I think. -
Simon about 6 yearsShouldn't you return &something with return type *Something as a good practice?
-
markeissler almost 6 yearsThis is incorrect. At best, you could set a tag value on that field and then get to its value with reflection but even with this the syntax is incorrect (missing back ticks) and you'd only be able to set a default value for a string type. If you have some insight as to what this example is referring to specifically please add a link to refer to.
-
M. Gopal over 5 yearsTo Value add Amit's one, It will be better to go with singleton instead of generating the struct every time
-
Juliatzin over 4 yearsIt is good to set default, but sometimes, I might want to override default. In this case, I won't be able to initialize a struct with a value that is not the default. a little annoying for me
-
Nordes over 4 yearsThank's a lot! I started to write the same code as the library suggested and came across this post. It does exactly what you expect (github.com/creasty/defaults). If you have no value it sets the default, but if you assigned a value to your variable, then it's going to not assign the default. It works pretty well with the yaml.v2 library.
-
ton about 3 yearsThis is a nice alternative, but it's not from
golang
. You have a generic constructor that use reflections. A real default value would be set automatically on every new struct instance. -
John Isaac over 2 years@edam how often does that come up? Do any of the stdlib functions do this for user defined types?
-
starriet over 2 yearsThe first quote has been modified to: "You may choose to make your type unexported, and provide an exported constructor function like
NewMyType()
in which you can properly initialize your struct / type. ... you can stop worrying about improper initialization."