DEV Community

Cover image for Constructors in Go?
Stefan Alfbo
Stefan Alfbo

Posted on

Constructors in Go?

In the world of Go programming, managing the initialization of structs is a common task. Structures in Go can often be initialized using their zero values. However, there are scenarios where these zero values do not represent meaningful defaults, or when initialization requires specific parameters.

In my post, func init(){}, I'm making some parallels with OOP constructors when describing the init function in Go. However that feature do not work that great with generic initialization of data structures. Lets look how this is done in Go.

As an example we will use this Person struct.

type Person struct {
  firstName
  lastName
}
Enter fullscreen mode Exit fullscreen mode

Initializing a struct within the same package is straightforward, as illustrated by the following example:

person := Person{
    firstName: "John",
    lastName:  "Doe",
}
Enter fullscreen mode Exit fullscreen mode

However, this approach encounters issues when used in a different package due to the private nature of the fields. Restricting access to struct fields by making them private is a common practice. This encapsulation helps enforce certain conditions, or invariants, when initializing the data structure. For instance, you might want to ensure that the firstName field is never an empty string, or there may be other properties on the struct that require specific conditions to be met for proper initialization.

The solution to this is to create an initialization function. These functions are usually named, New<struct name>, so in this case we would call the function, NewPerson.

func NewPerson(firstName, lastName string) *Person {
    return &Person{
        firstName: firstName,
        lastName:  lastName,
    }
}
Enter fullscreen mode Exit fullscreen mode

or if we want to enforce a certain condition.

func NewPerson(firstName, lastName string) (*Person, error) {
    if firstName == "" {
        return nil, fmt.Errorf("firstName cannot be empty")
    }
    return &Person{
        firstName: firstName,
        lastName:  lastName,
    }, nil
}
Enter fullscreen mode Exit fullscreen mode

A common pattern is to define a constructor function that returns a pointer to a new instance of the struct as the example above.

However it's is also possible to return the new struct as a value instead.

func MakePerson(firstName, lastName string) Person {
    return Person{
        firstName: firstName,
        lastName:  lastName,
    }
}
Enter fullscreen mode Exit fullscreen mode

It's not that uncommon to name the function with the prefix, Make, instead of, New, to indicate that it doesn't return a struct pointer.

That's it, naming convention, keep it simple and straightforward seems to be the recipe of Go.

You can read more about constructors and composite literals in the Go documentation, Effective Go.

Happy hacking!

Top comments (0)