ZetCode

Golang struct keyword

last modified May 7, 2025

This tutorial explains how to use the struct keyword in Go. We'll cover struct basics with practical examples of creating and using custom types.

The struct keyword defines a composite data type that groups together variables under a single name. Structs are fundamental for creating complex data structures in Go.

In Go, structs can contain fields of different types, methods, and can implement interfaces. They provide a way to create custom types that model real-world entities and relationships.

Basic struct definition

The simplest struct contains named fields with their types. This example shows how to define and initialize a basic struct.

basic_struct.go
package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func main() {
    var p1 Person
    p1.Name = "Alice"
    p1.Age = 30
    
    p2 := Person{"Bob", 25}
    
    fmt.Println(p1)
    fmt.Println(p2)
}

We define a Person struct with Name and Age fields. The example shows two initialization methods: field-by-field and using a struct literal.

Anonymous structs

Go supports anonymous structs for one-time use cases. This example demonstrates creating and using an unnamed struct type.

anonymous_struct.go
package main

import "fmt"

func main() {
    book := struct {
        Title  string
        Author string
        Pages  int
    }{
        Title:  "The Go Programming Language",
        Author: "Alan Donovan",
        Pages:  380,
    }
    
    fmt.Printf("%+v\n", book)
}

The anonymous struct is defined and initialized in one step. This is useful when you need a temporary structure without declaring a new type.

Nested structs

Structs can contain other structs to model complex relationships. This example shows nested struct composition.

nested_struct.go
package main

import "fmt"

type Address struct {
    Street  string
    City    string
    Country string
}

type Person struct {
    Name    string
    Age     int
    Address Address
}

func main() {
    p := Person{
        Name: "Charlie",
        Age:  35,
        Address: Address{
            Street:  "123 Main St",
            City:    "Boston",
            Country: "USA",
        },
    }
    
    fmt.Printf("%+v\n", p)
}

The Person struct contains an Address struct. This creates a hierarchical data structure that models real-world relationships.

Struct methods

Structs can have methods attached to them. This example demonstrates defining and calling methods on a struct type.

struct_methods.go
package main

import "fmt"

type Rectangle struct {
    Width  float64
    Height float64
}

func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}

func main() {
    rect := Rectangle{Width: 10, Height: 5}
    fmt.Println("Area:", rect.Area())
    
    rect.Scale(2)
    fmt.Println("Scaled Area:", rect.Area())
}

The Area method uses a value receiver, while Scale uses a pointer receiver. Pointer receivers can modify the original struct.

Struct tags

Struct tags provide metadata about fields. This example shows JSON tags for serialization.

struct_tags.go
package main

import (
    "encoding/json"
    "fmt"
)

type User struct {
    ID        int    `json:"id"`
    Username  string `json:"username"`
    Email     string `json:"email,omitempty"`
    IsActive  bool   `json:"-"`
}

func main() {
    u := User{
        ID:       1,
        Username: "johndoe",
        Email:    "",
        IsActive: true,
    }
    
    data, _ := json.Marshal(u)
    fmt.Println(string(data))
}

The tags control JSON field names and behavior. omitempty skips empty fields, and - excludes fields from serialization.

Struct embedding

Go supports embedding structs to achieve composition. This example demonstrates field and method promotion.

struct_embedding.go
package main

import "fmt"

type Contact struct {
    Email string
    Phone string
}

func (c Contact) Info() string {
    return fmt.Sprintf("%s | %s", c.Email, c.Phone)
}

type Employee struct {
    Name string
    Contact
}

func main() {
    emp := Employee{
        Name: "Jane Doe",
        Contact: Contact{
            Email: "[email protected]",
            Phone: "555-1234",
        },
    }
    
    fmt.Println(emp.Info())
    fmt.Println(emp.Email)
}

The Contact fields and methods are promoted to the Employee struct. This provides a way to compose functionality without inheritance.

Struct comparison

Structs can be compared if all their fields are comparable. This example shows equality checking between struct instances.

struct_comparison.go
package main

import "fmt"

type Point struct {
    X, Y int
}

func main() {
    p1 := Point{1, 2}
    p2 := Point{1, 2}
    p3 := Point{2, 3}
    
    fmt.Println("p1 == p2:", p1 == p2)
    fmt.Println("p1 == p3:", p1 == p3)
    
    type Person struct {
        Name string
        Age  int
    }
    
    // person1 := Person{"Alice", 30}
    // person2 := Person{"Alice", 30}
    // fmt.Println(person1 == person2) // Valid
    
    // type Data struct {
    //     Info map[string]string
    // }
    // d1 := Data{Info: make(map[string]string)}
    // d2 := Data{Info: make(map[string]string)}
    // fmt.Println(d1 == d2) // Invalid: map fields are not comparable
}

Structs with comparable fields can be compared with ==. The example also shows cases where comparison isn't possible due to uncomparable fields.

Source

Go language specification

This tutorial covered the struct keyword in Go with practical examples of creating and using custom data structures.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Golang tutorials.