Start learning free

LESSON 182 OF 338 · OBJECT-ORIENTED PROGRAMMING

Constructors in Go: NewXxx Functions

Lesson Read the full explanation

TL ; DR:

  • A constructor is a special function that runs when you create an object. It's used to set up the object's initial state.


  • In Go, the convention is to write a NewXxx function that takes parameters and returns an initialized struct:

    type Dog struct {
        name string
        age  int
    }
    
    func NewDog(name string, age int) Dog {
        return Dog{name: name, age: age}
    }
    

  • Then create objects with arguments: rex := NewDog("Rex", 4) — the constructor function fills in the fields for you.



Full lesson:

In the previous lesson you set member variables one at a time after creating the object:

var dog Dog
dog.name = "Rex"
dog.age = 4

That works, but it's verbose and easy to forget. Constructor functions let you initialize the fields the moment the object is created.


Defining a constructor

A Go constructor is a regular function with two distinguishing features:

  • By convention, its name starts with New followed by the type name (NewDog for a Dog struct).

  • It returns the struct type — Go constructor functions return an initialized value.

func NewDog(name string, age int) Dog {
    return Dog{name: name, age: age}
}

Struct literal initialization

Inside the constructor, Go uses a struct literal Dog{name: name, age: age} to build the value. The left-hand name is the field name, and the right-hand name is the parameter — there is no ambiguity because Go uses named fields rather than a this pointer.


Calling the constructor

rex := NewDog("Rex", 4)
luna := NewDog("Luna", 7)

By the time these lines finish, rex.name is already "Rex", rex.age is 4, and the same for Luna.


Your task

The Dog struct already has the name and age fields. Add a NewDog constructor function that takes a name string and an age int and returns an initialized Dog. Then in mainFunction, create two dogs:

rex := NewDog("Rex", 4)
luna := NewDog("Luna", 7)

Expected output:

Rex is 4
Luna is 7
STEP 1 OF 2
    Ctrl + Enter to check

    GO · OBJECT-ORIENTED PROGRAMMING

    Constructors in Go, explained

    Why Go has no constructors

    In many languages a constructor is a special member of a class that runs when you create an object. Go has no such feature. A struct value can be created anywhere with a literal, and Go does not run any code when it happens. The convention that fills the gap is a plain function, usually named New followed by the type name, that builds the value, sets up its fields and returns it.

    Setting fields by hand after creating the value works, but it is verbose and easy to forget:

    var dog Dog
    dog.name = "Rex"
    dog.age = 4
    

    A constructor function does all of it in one call.

    Writing a constructor function

    A constructor function is an ordinary function with two habits:

    • Its name starts with New, then the type name: NewDog for Dog. The prefix is only a convention, and Go treats the function like any other.
    • It returns the finished value.
    type Dog struct {
        name string
        age  int
    }
    
    func NewDog(name string, age int) Dog {
        return Dog{name: name, age: age}
    }
    

    Inside, Dog{name: name, age: age} is a struct literal with named fields. In each pair the part before the colon is the field and the part after it is the parameter, so name: name is not a typo. Because the fields are named, the order does not matter, and any field you leave out gets its zero value.

    Calling it

    rex := NewDog("Rex", 4)
    luna := NewDog("Luna", 7)
    

    When these lines finish, rex.name is "Rex" and rex.age is 4, and luna holds its own values. Each call builds a separate value.

    Value or pointer, and validation

    This lesson's NewDog returns a Dog value. Many Go constructors return a pointer, *Dog, by writing return &Dog{name: name, age: age}. Returning a pointer avoids copying a large struct and lets all callers share one object. For a small struct a value is fine. Either way the calling code looks the same, and rex.name works on both.

    A constructor is also the right place for checks, because it is the one function every new object passes through. A constructor that can fail commonly returns an error as a second result:

    func NewDogChecked(name string, age int) (Dog, error) {
        if age < 0 {
            return Dog{}, fmt.Errorf("age %d is negative", age)
        }
        return Dog{name: name, age: age}, nil
    }
    

    The exercise does not need this, but it shows what a plain function allows that a built-in constructor would not.

    The lesson's exercise

    The Dog struct already has name and age. The task has two parts.

    1. Declare NewDog below the struct, with parameters name string and age int, returning a Dog built from a literal that sets both fields.
    2. Create the dogs in mainFunction with :=, calling NewDog("Rex", 4) and NewDog("Luna", 7). The code below them prints the fields.
    type Dog struct {
        name string
        age int
    }
    
    func NewDog(name string, age int) Dog {
        return Dog{name: name, age: age}
    }
    
    
    
    func mainFunction() {
        rex := NewDog("Rex", 4)
        luna := NewDog("Luna", 7)
        fmt.Printf("%s is %d\n", rex.name, rex.age)
        fmt.Printf("%s is %d\n", luna.name, luna.age)
    }
    

    It prints:

    Rex is 4
    Luna is 7
    

    In Printf, %s formats a string and %d an integer, and the \n ends the line, since Printf adds no newline itself.

    Common mistakes

    • Swapping the arguments. NewDog(4, "Rex") does not compile, because the types of the parameters differ. When two parameters share a type, the compiler cannot catch a swap, so check the order.
    • Expecting an automatic call. Writing var d Dog never calls NewDog. The constructor runs only when you call it, so a zero-value Dog can exist with an empty name.
    • Omitting the field names. The unkeyed form Dog{name, age} compiles, but it depends on the order of the fields in the struct and breaks as soon as a field is added or moved. Prefer the keyed form.
    • Naming the constructor in lower case. newDog works inside the package but is hidden from other packages. Use NewDog when other packages should call it.

    Key takeaways

    • Go has no constructors; a NewXxx function is the convention.
    • A struct literal with named fields builds the value.
    • The function can return a value or a pointer, and can return an error if arguments are invalid.
    • Nothing forces callers to use the constructor, so design the zero value to be usable too.
    Keep going with GoAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free