Constructors in Go

Go has objects. Objects can have constructors (although not automatic constructors). And finally, Go is an OOP language (data types have methods attached, but admittedly there are endless definitions of what OOP is.)

Nevertheless, the accepted best practice is to write zero or more constructors for your types.

As @dystroy posted his answer before I finished this answer, let me just add an alternative version of his example constructor, which I would probably write instead as:

func NewThing(someParameter string) *Thing {
    return &Thing{someParameter, 33} // <- 33: a very sensible default value
}

The reason I want to show you this version is that pretty often "inline" literals can be used instead of a "constructor" call.

a := NewThing("foo")
b := &Thing{"foo", 33}

Now *a == *b.


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.


There are actually two accepted best practices:

  1. 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).
  2. Provide a function func New() YourTyp or if you have several such types in your package functions func NewYourType1() YourType1 and 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.)