Start learning free

LESSON 180 OF 338 · OBJECT-ORIENTED PROGRAMMING

Defining a Class in Go: Struct Types

Lesson Read the full explanation

TL ; DR:

  • A class is a blueprint for creating objects. It groups together related data and behavior under a single name.


  • In Go, you define a struct type with the type keyword, followed by the type name, the struct keyword, and a pair of curly braces:

    type Dog struct {
    }
    

    The body of the struct can be empty — that's still a valid type. We'll add data and behavior to it in the next lessons.



Full lesson:

So far, you've worked with built-in types like int, string, and arrays. But what if you want to model something the language doesn't have a type for — like a Dog, a BankAccount, or a Game?

That's what classes are for. A class lets you define your own type by listing what data it holds and what actions it can perform.


Why classes?

Imagine you're writing a program about dogs. Each dog has a name, an age, and can bark. Without classes, you'd have to track each dog's name in one variable, age in another, and write a separate bark() function for each. That gets messy fast.

With a class, you bundle all of that into one neat package called Dog:

type Dog struct {
    // We'll add fields and methods in upcoming lessons.
}

The syntax

Defining an empty struct type in Go looks like this:

type TypeName struct {
}

Three things to notice:

  • The keyword type tells Go you're defining a new type, and struct specifies that it's a struct.

  • TypeName is the name you choose. By convention, Go type names use PascalCase — capitalized words with no underscores: Dog, BankAccount, HighScore.

  • The curly braces { } hold the body of the struct. Unlike C++, Go does not require a semicolon after the closing brace.


No classes: struct + receiver methods:

Go has no class keyword. You define a struct for the data, then attach behavior with methods that take a receiver — the value in parentheses before the method name. You call it with dot syntax, just like a method on an object.

type Dog struct {
}

func (d Dog) bark() {
    fmt.Println("Woof!")
}

d.bark() // Woof!

You'll see this func (d Dog) ... receiver style throughout the coding tutorials — it's how Go gives a type its behavior without classes.


Your task

Define an empty struct type called Dog. The pre-filled code in mainFunction will create an instance of your type and print a confirmation message. If you define the type correctly, the program will compile and print:

Defined the Dog class!
STEP 1 OF 1
    Ctrl + Enter to check

    GO · OBJECT-ORIENTED PROGRAMMING

    Defining A Class in Go, explained

    What a "class" means in Go

    Go has no class keyword. The job a class does in other languages, bundling data and behaviour under one name so you can model a Dog, a BankAccount or a Game, is done by a struct type. You declare the data as fields of the struct, and you attach behaviour with methods, which later lessons add one piece at a time.

    This lesson covers the first piece: declaring a new type. The lesson's examples call fmt.Println, so they assume import "fmt" at the top of the file.

    The syntax

    type Dog struct {
    }
    

    Reading it from left to right:

    • type tells Go you are declaring a new type.
    • Dog is the name you chose. Go programmers write type names in PascalCase: Dog, BankAccount, HighScore. A capital first letter also has a meaning, covered in the access modifiers lesson.
    • struct says the type is a record made of fields.
    • The braces hold the fields. Here they are empty, which is a valid type. A struct with no fields is a normal type, and it is common for types that only carry methods.

    Go needs no semicolon after the closing brace. A one-line form is equally valid:

    type Dog struct{}
    

    Creating a value of the type

    Once Dog exists, Dog{} creates a value of it. This is a composite literal: the type name followed by braces. With no fields to fill in, the braces stay empty.

    dog := Dog{}
    fmt.Println(dog)
    

    This prints {}, the default formatting of a struct with no fields. The next lessons cover creating values in more detail and giving the struct fields.

    Types with behaviour: receivers

    You give a type behaviour by declaring a function with a receiver, the parameter in parentheses between func and the method name:

    type Dog struct {
    }
    
    func (d Dog) bark() {
        fmt.Println("Woof!")
    }
    

    Now any Dog value can call bark with dot syntax, for example dog.bark(). The method lives outside the braces of the struct. In Go, the type declaration holds only the data, and methods are declared separately, anywhere in the same package. The lessons in this chapter use the receiver name this, borrowed from other languages. Most Go code uses a short name based on the type, such as d for Dog, and both compile.

    The lesson's exercise

    The task is to declare an empty struct type called Dog. The code already in mainFunction creates a Dog and prints a confirmation, so the only missing piece is the type.

    1. Write the declaration at the top of the file, outside any function, because type declarations and function declarations both live at the package level.
    2. Use the exact name Dog. Go is case-sensitive, so dog would be a different identifier from the Dog that mainFunction uses.
    type Dog struct {}
    
    
    
    func mainFunction() {
        dog := Dog{}
        _ = dog
        fmt.Println("Defined the Dog class!")
    }
    

    The program prints:

    Defined the Dog class!
    

    The line _ = dog is there because Go refuses to compile a function that declares a local variable and never uses it. Assigning the value to the blank identifier _ counts as a use that discards it.

    Common mistakes

    • Looking for the class keyword. There is none. Writing class Dog {} is a syntax error.
    • Putting the declaration inside a function by accident. That is legal, but then the type exists only inside that function, so mainFunction would not see it.
    • Using the type without the braces. dog := Dog does not compile, because Dog is a type and not a value. Write Dog{}.
    • Declaring a variable and not using it. An unused local variable is a compile error in Go, not a warning.
    • Adding a semicolon after the braces out of habit from C++. It is not needed.

    Key takeaways

    • A struct type is Go's replacement for a class: type Name struct { ... }.
    • The body may be empty, and the type is still real.
    • Create a value with a composite literal such as Dog{}.
    • Behaviour comes from methods with a receiver, declared outside the struct.
    • Type names use PascalCase by convention.
    Keep going with GoAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free