Start learning free

LESSON 183 OF 338 · OBJECT-ORIENTED PROGRAMMING

Class Fields in Go: Struct Fields

Lesson Read the full explanation

TL ; DR:

  • A field is a variable that lives inside a struct. Each value of that struct type has its own copy.


  • Declare fields inside a type ... struct block so other code can read and write them:

    type Dog struct {
        name string
        age  int
    }
    

  • Access them on a value with the dot operator: dog.name = "Rex"



Full lesson:

Right now your Dog struct is just an empty shell — every Dog value you create is identical. We need a way to attach data to each value.

That's what fields are for. A field is a variable that belongs to a struct — and each value created from that struct type gets its own copy of every field.


Declaring fields

type Dog struct {
    name string
    age  int
}
  • Fields with an uppercase first letter are exported — accessible from outside the package. Lowercase fields are accessible within the same package.

  • name string is a regular field declaration.


Reading and writing

dog := Dog{}
dog.name = "Rex"        // write
dog.age = 4
fmt.Println(dog.name)  // read

Each value has its own slot for every field, so two dogs can have different names without interfering.


Your task

Update the Dog struct to have two fields: name (a string) and age (an int). Then in mainFunction, set them on the dog value so the pre-filled fmt.Println prints:

Rex is 4 years old
STEP 1 OF 3
    Ctrl + Enter to check

    GO · OBJECT-ORIENTED PROGRAMMING

    Class Fields in Go, explained

    What a field is

    An empty struct type is a shell: every value of it is identical. A field is a variable that lives inside a struct, and every value of the struct type gets its own copy of each field. Fields are how a Dog knows its name and age.

    Declaring fields

    type Dog struct {
        name string
        age  int
    }
    

    Each field is its name followed by its type, one per line. There is no var keyword and no commas between fields. Fields of the same type can share a line, as in x, y int, but one per line reads better.

    The first letter of a field name controls its visibility. A capitalised name such as Name is exported and usable from other packages. A lowercase name such as name is visible only inside its own package. In these lessons everything sits in one package, so lowercase fields can be used freely.

    Reading and writing with the dot operator

    dog := Dog{}
    dog.name = "Rex"        // write
    dog.age = 4
    fmt.Println(dog.name)  // read
    

    The dot operator reaches a field of one particular value: dog.age is the age of this dog. Two dogs have separate fields, so changing one does not touch the other.

    Zero values

    A field you never set is not garbage and not an error. It holds the zero value of its type, which is "" for string, 0 for numbers and false for bool. The line dog := Dog{} therefore gives a dog with an empty name and age 0, and printing it with %+v shows {name: age:0}. This is why Go has no "uninitialised field" bugs of the kind found in some other languages, though an empty name can still be a logic bug.

    You can also set fields at creation with a literal that names them: Dog{name: "Rex", age: 4}. The next lesson, on constructors, builds on that.

    Fields at work: two dogs

    A struct with fields is also the usual way to pass related data around together. Instead of three separate variables for a dog's name, age and owner, one Dog value carries all three through function calls and into slices or maps.

    Because each value owns its fields, a program can keep several dogs side by side and change them independently:

    rex := Dog{name: "Rex", age: 4}
    luna := Dog{name: "Luna", age: 7}
    luna.age++
    fmt.Println(rex.age, luna.age) // 4 8
    

    Fields can have any type, including slices, maps, other structs and pointers. A field of struct type is reached by chaining dots, such as dog.owner.name. Two struct values whose fields are all comparable can be compared with ==, which is true when every field is equal.

    The lesson's exercise

    The Dog struct is empty and the starter code in mainFunction sets the age and prints the dog. Three edits complete it.

    1. Add the fields inside the struct: name as a string and age as an int.
    2. Declare dog at the top of mainFunction with dog := Dog{}. Both fields start at their zero values.
    3. Set the name with dog.name = "Rex". The age line is already in place.
    type Dog struct {
        name string
        age int
    }
    
    
    
    func mainFunction() {
        dog := Dog{}
        dog.name = "Rex"
        dog.age = 4
        fmt.Printf("%s is %d years old\n", dog.name, dog.age)
    }
    

    The program prints:

    Rex is 4 years old
    

    Common mistakes

    • Writing var or commas inside the struct. var name string, is a syntax error. Write name string.
    • Mixing up the order. Go puts the type after the name: age int, not int age.
    • Assigning the wrong type. dog.age = "four" does not compile, because age is an int.
    • Assuming a copy shares fields. other := dog copies every field, so changing other.name afterwards does not change dog.name.
    • Accessing a lowercase field from another package. That is a compile error. Capitalise the field, or give the type a method that exposes it.

    Key takeaways

    • Fields are declared inside type Name struct { ... } as name then type.
    • Each struct value has its own copy of every field.
    • The dot operator reads and writes a field.
    • Unset fields hold the zero value of their type.
    • Capitalised field names are exported, and lowercase ones are package-private.
    Keep going with GoAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free