Structs in Go

Structs in Go

In this tutorial, we are going to discuss structs in the Go language. A struct (short for “structure”) is a user-defined type that represents a collection of named fields/properties.

Structs in Go

Structs are used to group related data together to form a single unit. Any real-world entity that has a set of properties can be represented using a struct.

If you’re coming from an object-oriented background, you can think of a struct as a lightweight class that supports composition but not inheritance.

Structs help in improving the overall code quality by allowing us to create and pass complex data structures across multiple modules.

Imagine passing 10 parameters into a function; you’ll soon run away from code. This is exactly why structs are useful; now, instead of 10 parameters, you simply pass a single struct to that function.

For example, an employee has a firstName, lastName, age, and salary. It makes sense to group these three properties into a single struct named Employee.

Defining a struct type

A struct is declared using two keywords – type and struct. It is wrapped with curly brackets (just like classes in java), which contain fields with a defined type and an identifier(name). You can define a new struct type as follows

type Employee struct { 
    FirstName string 
    LastName  string 
    Age       int
    Salary    int
} 

The above snippet declares a struct type Employee with fields FirstName, LastName, Age, and Salary. The above Employee struct is called a named struct because it creates a new data type named Employee using employee struct.

The type keyword introduces a new type. It is followed by the name of the type (Employee) and the keyword struct to indicate that we are defining a struct. The struct contains a list of fields inside the curly braces. Each field has a name and a type.

This struct can also be made more compact by declaring fields that belong to the same type in a single line followed by the type name.

In the above struct, FirstName and LastName belong to the same type string and Age and Salary belong to the same type int; hence the struct can be rewritten as

type Employee struct { 
    FirstName, LastName string 
    Age, Salary         int 
} 
Initializing a struct

You can initialize a variable of a struct type using a struct literal as follows

emp := Employee{"Ashok Kumar", "Mariyala", 29, 50000}

Please note that you need to pass the field values in the same order in which they are declared in the struct. Also, you can’t initialize only a subset of fields with the above syntax.

emp := Employee{"Ashok Kumar"} // Compiler Error: too few values in struct initializer
Naming fields while initializing a struct

Go also supports the name: value syntax for initializing a struct (the order of fields is irrelevant when using this syntax).

emp := Employee{FirstName: "Ashok Kumar",Age:29,Salary:50000,LastName:"Mariyala"}

You can separate multiple fields by a new line for better readability (the trailing comma is mandatory in this case)

emp := Employee{
         FirstName: "Ashok Kumar",
         Age:       29,
         Salary:    50000,
         LastName:  "Mariyala",
}

The name: value syntax allows you to initialize only a subset of fields. All the uninitialized fields are set to their corresponding zero value

emp := Employee{FirstName: "Ashok Kumar",Age:29} // LastName: "", Salary:0

emp := Employee{} // FirstName:"" LastName: "", Salary:0, Age:0
package main

import (
    "fmt"
)

type Employee struct {
    FirstName string
    LastName  string
    Age       int
    Salary    int
}

func main() {
    //creating struct specifying field names
    emp1 := Employee{
        FirstName: "Ashok Kumar",
        Age:       29,
        Salary:    50000,
        LastName:  "Mariyala",
    }

    //creating struct without specifying field names
    emp2 := Employee{"Ashok Kumar", "Mariyala", 29, 5000}
    fmt.Println("Employee 1 : ", emp1)
    fmt.Println("Employee 2 : ", emp2)
}

Output

Employee 1 :  {Ashok Kumar Mariyala 29 50000} 
Employee 2 :  {Ashok Kumar Mariyala 29 5000}

Run in playground

Creating anonymous structs

In the Go language, it is possible to declare structs without creating a new data type. These types of structs are called anonymous structs.

package main

import (
    "fmt"
)

func main() {
    emp := struct {
        FirstName string
        LastName  string
        Age       int
        Salary    int
    }{
        FirstName: "Ashok Kumar",
        Age:       29,
        Salary:    50000,
        LastName:  "Mariyala",
    }
    fmt.Println("Employee : ", emp)
}

Output

Employee :  {Ashok Kumar Mariyala 29 50000}

Run in playground

Accessing fields of a struct

The dot . operator is used to access the individual fields of a struct.

package main

import (
    "fmt"
)

type Employee struct {
    FirstName string
    LastName  string
    Age       int
    Salary    int
}

func main() {
    emp := Employee{
        FirstName: "Ashok Kumar",
        Age:       29,
        Salary:    50000,
        LastName:  "Mariyala",
    }
    fmt.Println("Employee First Name : ", emp.FirstName)
    fmt.Println("Employee Last Name : ", emp.LastName)
    fmt.Println("Employee Age : ", emp.Age)
    fmt.Println("Employee Salary: ", emp.Salary)
}

Output

Employee First Name :  Ashok Kumar 
Employee Last Name :  Mariyala 
Employee Age :  29 Employee 
Salary:  50000

Run in playground

Zero value of a struct

When a struct is defined and it is not explicitly initialized with any value, the fields of the struct are assigned their zero values by default.

package main

import (
    "fmt"
)

type Employee struct {
    FirstName string
    LastName  string
    Age       int
    Salary    int
}

func main() {
     var emp Employee
     
     fmt.Println("Employee First Name : ", emp.FirstName) 
     fmt.Println("Employee Last Name : ", emp.LastName) 
     fmt.Println("Employee Age : ", emp.Age) 
     fmt.Println("Employee Salary: ", emp.Salary)
}

Output

Employee First Name :   
Employee Last Name :   
Employee Age :  0 
Employee Salary:  0

Run in playground

Pointers to a struct

In Go language, it is possible to create pointers to a struct.

package main

import (
    "fmt"
)

type Employee struct {
    FirstName string
    LastName  string
    Age       int
    Salary    int
}

func main() {
    emp := &Employee{
        FirstName: "Ashok Kumar",
        Age:       29,
        Salary:    50000,
        LastName:  "Mariyala",
    }
    fmt.Println("Employee First Name : ", (*emp).FirstName)
    fmt.Println("Employee Last Name : ", (*emp).LastName)
    fmt.Println("Employee Age : ", (*emp).Age)
    fmt.Println("Employee Salary: ", (*emp).Salary)
}

Output

Employee First Name :  Ashok Kumar 
Employee Last Name :  Mariyala 
Employee Age :  29 Employee 
Salary:  50000

Run in playground

The Go language gives us the option to use emp.FirstName instead of the explicit dereference (*emp).FirstName to access the FirstName field.

package main

import (
    "fmt"
)

type Employee struct {
    FirstName string
    LastName  string
    Age       int
    Salary    int
}

func main() {
    emp := &Employee{
        FirstName: "Ashok Kumar",
        Age:       29,
        Salary:    50000,
        LastName:  "Mariyala",
    }
    fmt.Println("Employee First Name : ", emp.FirstName)
    fmt.Println("Employee Last Name : ", emp.LastName)
    fmt.Println("Employee Age : ", emp.Age)
    fmt.Println("Employee Salary: ", emp.Salary)
}

Output

Employee First Name :  Ashok Kumar 
Employee Last Name :  Mariyala 
Employee Age :  29 Employee 
Salary:  50000

Run in playground

Anonymous fields

In Go language, it is possible to create structs with fields that contain only a type without the field name. These kinds of fields are called anonymous fields.

The snippet below creates a struct Person which has two anonymous fields string and int

type Person struct {
       string
       int
}

Even though anonymous fields do not have an explicit name, by default, the name of an anonymous field is the name of its type.

package main

import (
    "fmt"
)

type Person struct {
    string
    int
}

func main() {
    person := Person{
        string: "Ashok Kumar",
        int:    29,
    }
    fmt.Println(person.string)
    fmt.Println(person.int)
}

Output

Ashok Kumar 
29

Run in playground

Nested structs

In Go language, a struct may contain a field which in turn is a struct. These kinds of structs are called nested structs.

package main

import (
    "fmt"
)

type Address struct {
    City  string
    State string
}

type Person struct {
    Name    string
    Age     int
    Address Address
}

func main() {
    person := Person{
        Name: "Ashok Kumar",
        Age:  29,
        Address: Address{
            City:  "Hyderabad",
            State: "Telangana",
        },
    }
    fmt.Println("Name:", person.Name) 
    fmt.Println("Age:", person.Age) 
    fmt.Println("City:", person.Address.City)  
    fmt.Println("State:", person.Address.State)
}

Output

Name: Ashok Kumar 
Age: 29 
City: Hyderabad 
State: Telangana 

Run in playground

Structs Equality

Structs are value types and are comparable if each of their fields is comparable. Two struct variables are considered equal if their corresponding fields are equal.

package main

import (
    "fmt"
)

type name struct {
    FirstName string
    LastName  string
}

func main() {
    name1 := name{
        FirstName: "Ashok Kumar",
        LastName:  "Mariyala",
    }
    name2 := name{
        FirstName: "Ashok Kumar",
        LastName:  "Mariyala",
    }
    if name1 == name2 {
        fmt.Println("name1 and name2 are equal")
    } else {
        fmt.Println("name1 and name2 are not equal")
    }
   
    name3 := name{
        FirstName: "Ashok Kumar",
        LastName:  "Mariyala",
    }
    name4 := name{
        FirstName: "Ashok Kumar",
    } 
    if name3 == name4 {
        fmt.Println("name3 and name4 are equal")
    } else {
        fmt.Println("name3 and name4 are not equal")
    }
}

Output

name1 and name2 are equal 
name3 and name4 are not equal

Run in playground

In the above program, the name struct type contains two string fields. Since strings are comparable, it is possible to compare two struct variables of the type name. Struct variables are not comparable if they contain fields that are not comparable.

Exported and UnExported fields of a struct

Go doesn’t have any public, private, or protected keyword. The only mechanism to control the visibility outside the package is using the capitalized and non-capitalized formats.

  • Capitalized Identifiers are exported. The capital letter indicates that this is an exported identifier and is available outside the package.
  • Non-capitalized identifiers are not exported. The lowercase indicates that the identifier is not exported and will only be accessed within the same package.

So any struct which starts with a capital letter is exported to other packages. Similarly, any struct field which begins with capital is exported; otherwise, not.

That’s all about the Structs in Go language. If you have any queries or feedback, please write us email at contact@waytoeasylearn.com. Enjoy learning, Enjoy Go language.!!

Structs in Go
Scroll to top