5 min read

Understanding the Basics: A Beginner's Guide to Golang Structs

Understand Golang structs effortlessly with our beginner-friendly guide. Start learning and mastering programming concepts today
Understanding the Basics: A Beginner's Guide to Golang Structs
Photo by JJ Ying / Unsplash

Welcome to our beginner's guide to understanding Golang structs. In this article, we will delve into the basics of Golang structs, providing a clear and concise overview for those new to the language. Whether you are just starting out with Golang or looking to refresh your knowledge, this guide will equip you with the fundamental understanding of structs in Golang. Let's dive in.

Introduction

In the world of programming with Go (often referred to as Golang), understanding the concept of structs is crucial for every developer, whether you're just starting out or looking to deepen your existing knowledge. The term "struct" is short for "structure" and is a key element in Golang's approach to organizing and managing data. This guide aims to demystify the concept of Golang structs and provide a clear understanding of how they are used, especially focusing on Golang struct methods.

Structs in Golang offer a way to define and group together data under a single name, making it easier to handle complex data structures. Unlike classes in some other programming languages, Golang structs are simple yet powerful. They allow developers to create more modular and maintainable code. This is particularly important in Go, where simplicity and efficiency are core principles.

What are structs in Golang?

Structs in Golang, often simply referred to as "golang structs," are a crucial feature of the Go programming language. They offer a versatile way to group together related data. Understanding golang structs is essential for anyone looking to master Go, as they form the backbone of data organization and encapsulation in this language.

Syntax and Basic Structure of Golang Structs

The basic syntax for defining a struct in Go is straightforward. Here’s a simple example:

type Person struct {
    Name string
    Age  int
}

Golang Struct Definition

In this example, Person is a struct with two fields: Name and Age. The type keyword introduces a new type definition, followed by the name of the struct (Person), the struct keyword, and then a list of fields enclosed in curly braces. Each field has a name and a type.

Explanation of Fields and Types within a Struct

The power of golang structs comes from their ability to hold fields of different types. For instance, a struct can contain integers, strings, slices, maps, or even other structs. This versatility makes them an excellent tool for data modeling.

Consider an extended example:

type Address struct {
    Street string
    City   string
    ZipCode int
}

type Employee struct {
    PersonalInfo Person
    Position     string
    Salary       int
    Address      Address
}

Go Struct as field type

Here, Address and Person are structs used as fields within the Employee struct. This nesting of structs is a common practice in Go and showcases the language's ability to handle complex data structures effectively.

Embedding Golang Structs

Golang does not support inheritance in a classic way. It was designed by following the "Composition over Inheritance" principle, in which Golang structs could be embedded. Let's take a look on following example:

type Employee struct {
    Person
    Position     string
    Salary       int
    Address      Address
}

Golang structs embedding

In this version of Employee struct, we changed the personal info of the employee to be embedded directly, by not through the PersonalInfo field:

p := Employee{
    Person: Person{
        Name: "John Smith",
        Age:  50,
    },
}
fmt.Println(p.Name) // -> John Smith

Embedded Golang structs usage

This way, we extended the Employee struct, by defining an embedded Person struct field, but the fields of the embedded struct are accessible directly by the extended struct.

Golang Struct Methods

While structs in Go primarily hold data, you can also associate functions with them, known as "golang struct methods." These methods allow you to define behaviors on your structs, much like methods in object-oriented programming languages.

Here's an example of adding a method to our Person struct:

func (p Person) FullName() string {
    return p.Name
}

Value receiver method definition in Golang

This FullName method is associated with the Person struct. The (p Person) part is known as the receiver, specifying that the method is tied to the Person struct. This method returns the Name of the person, demonstrating a simple behavior encapsulated within the struct.

There are usually two types of receivers for methods in Go: pointer and value receivers. The example for FullName() method show how to declare a method with value receiver.
Let's take a look on a following example, and change the age of a Person by incrementing one year:

func (p *Person) Grow() {
    p.Age += 1
}

Pointer receiver method definition in Golang

As you might noticed, the difference with previous example is that receiver has this structure (p *Person). This means that the receiver is actually a pointer to the instance of a struct, compared to a value receiver when we receive a copy of the instance value.

The difference between these two, is that the value receiver instance exists during the method call lifetime, and it's cleaned up from the call stack after it ends, and any changes applied to that copy are removed as well. On the other hand, when we receive a pointer, it's actually a copy of a reference too, but it still refer to the struct instance, therefore any changes applied to the pointer of the instance, will occur on instance itself.

In simple words, a pointer receiver changes the state of a struct instance, whereas value receiver don't. It's usefull to have value receivers when there is some processing that takes instance current state as input, and creates a different output. If we need change the current state of the instance, we will use pointer receiver.

There are some caveats when designing structs for using pointer receiver and value receiver, which we will discuss in other article.

Implementing Interfaces with Structs

Interfaces in Go provide a way to specify the behavior of an object. If a type (such as a struct) has all the methods that an interface declares, it is said to implement that interface. This feature is essential for creating modular and interchangeable code in Go.

Example:

type Greeter interface {
    Greet() string
}

func (p Person) Greet() string {
    return "Hello, " + p.FullName()
}

// Person now implicitly implements Greeter interface

Interface implementation in a Golang struct

In this example, the Person struct implements the Greeter interface by providing a Greet method. Go does not require explicit declaration to implement an interface, which simplifies the code and enhances its readability.

Advantages of Using Methods and Interfaces with Structs

Combining "golang struct methods" and interfaces brings several advantages:
1. Encapsulation: Methods allow you to encapsulate behavior within your structs. This means you can keep the struct's data and the operations on that data together.
2. Reusability: By implementing interfaces, structs can be used interchangeably where the interface is expected. This makes your code more modular and reusable.
3. Abstraction: Interfaces provide a level of abstraction, allowing you to change the underlying implementation without affecting the code that uses the interface.

Conclusion

In this comprehensive guide, we've journeyed through the fundamental concepts of Golang struct, exploring their versatility and functionality in Go programming. Starting with the basics, we learned that Golang structs are a powerful tool for grouping related data, serving as the cornerstone for structuring complex data in Go applications.

We examined the syntax and structure of Golang structs, highlighting the ease and flexibility of defining custom data types. Through practical examples, we demonstrated how to declare, initialize, and manipulate struct fields, providing you with the foundational skills to effectively use structs in your Go projects.

A crucial aspect we delved into was the implementation of methods with structs. Golang struct methods are integral for adding behavior to our data structures, allowing us to encapsulate functionality within our structs. This not only makes our code more organized and readable but also paves the way for more advanced concepts like interface implementation.