How to set default values in Go structs

GoStructInitializationDefault Value

Go Problem Overview


There are multiple answers/techniques to the below question:

  1. How to set default values to golang structs?
  2. How to initialize structs in golang

I have a couple of answers but further discussion is required.

Go Solutions


Solution 1 - Go

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 2 - Go

  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.

  2. 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 3 - Go

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 - Go

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 - Go

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
}

Solution 6 - Go

What about making something like this:

// Card is the structure we work with
type Card struct {
	Html        js.Value
	DefaultText string `default:"html"` // this only works with strings
}

// Init is the main function that initiate the structure, and return it
func (c Card) Init() Card {
	c.Html = Document.Call("createElement", "div")
	return c
}

Then call it as:

c := new(Card).Init()

Solution 7 - Go

One way to do that is:

// declare a type
type A struct {
	Filed1 string
	Field2 map[string]interface{}
}

So whenever you need a new variable of your custom defined type just call the NewA function also you can parameterise the function to optionally assign the values to the struct fields

func NewA() *A {
	return &A{
		Filed1: "",
		Field2: make(map[string]interface{}),
	}
}

Solution 8 - Go

for set default values in Go structs we use anonymous struct:

Person := struct {
    name      string
    age       int
    city      string
}{
    name:      "Peter",
    age:        21,
    city:      "Noida",
}

fmt.Println(Person)

Solution 9 - Go

I found this thread very helpful and educational. The other answers already provide good guidance, but I wanted to summarize my takeaways with an easy to reference (i.e. copy-paste) approach:

package main

import (
	"fmt"
)

// Define an interface that is exported by your package.
type Foo interface {
  GetValue() string // A function that'll return the value initialized with a default.
  SetValue(v string) // A function that can update the default value.
}

// Define a struct type that is not exported by your package.
type foo struct {
  value string
}

// A factory method to initialize an instance of `foo`,
// the unexported struct, with a default value.
func NewFoo() Foo {
  return &foo{
    value: "I am the DEFAULT value.",
  }
}

// Implementation of the interface's `GetValue`
// for struct `foo`.
func (f *foo) GetValue() string {
  return f.value
}

// Implementation of the interface's `SetValue`
// for struct `foo`.
func (f *foo) SetValue(v string) {
  f.value = v
}

func main() {
  f := NewFoo()
  fmt.Printf("value: `%s`\n", f.GetValue())
  f.SetValue("I am the UPDATED value.")
  fmt.Printf("value: `%s`\n", f.GetValue())
}

Solution 10 - Go

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPrateekView Question on Stackoverflow
Solution 1 - Govodolaz095View Answer on Stackoverflow
Solution 2 - GoPrateekView Answer on Stackoverflow
Solution 3 - Gowolfson109View Answer on Stackoverflow
Solution 4 - GoMike ChiricoView Answer on Stackoverflow
Solution 5 - GoRdBView Answer on Stackoverflow
Solution 6 - GoHasan A YousefView Answer on Stackoverflow
Solution 7 - GoDipto MondalView Answer on Stackoverflow
Solution 8 - GoAbhibgnView Answer on Stackoverflow
Solution 9 - GoOlshanskView Answer on Stackoverflow
Solution 10 - Gouser10209901View Answer on Stackoverflow