Golang Tutorial

Fundamentals

Control Statements

Functions & Methods

Structure

Arrays & Slices

String

Pointers

Interfaces

Concurrency

Structures in Golang

Structures (commonly known as structs) are a way to combine multiple fields of possibly different data types into a single data type. This tutorial will guide you through the essentials of working with structs in Go.

1. Declaring and Initializing Structs

Defining a struct involves providing a name for the struct type and then defining its fields.

package main

import "fmt"

// Defining a struct
type Person struct {
    FirstName string
    LastName  string
    Age       int
}

func main() {
    // Initializing a struct
    person1 := Person{"John", "Doe", 30}
    fmt.Println(person1)  // Outputs: {John Doe 30}

    // Named fields initialization
    person2 := Person{
        FirstName: "Jane",
        LastName:  "Smith",
        Age:       25,
    }
    fmt.Println(person2)  // Outputs: {Jane Smith 25}
}

2. Accessing Struct Fields

To access or modify a field of a struct, use the dot (.) operator.

p := Person{"Alice", "Johnson", 28}
fmt.Println(p.FirstName)  // Outputs: Alice

p.Age = 29
fmt.Println(p.Age)  // Outputs: 29

3. Pointers to Structs

You can create pointers to structs, which allows you to modify the struct through the pointer.

p := &Person{"Bob", "Taylor", 40}
p.Age = 41  // Same as (*p).Age = 41
fmt.Println(p.Age)  // Outputs: 41

4. Anonymous Structs

Go supports defining and instantiating structs without formally declaring a new type.

point := struct {
    X, Y int
}{1, 2}
fmt.Println(point)  // Outputs: {1 2}

5. Nested Structs

Structs can be nested to create more complex data structures.

type Address struct {
    City, State, Country string
}

type Employee struct {
    Name    string
    Age     int
    Address Address
}

e := Employee{
    Name: "Charlie",
    Age:  32,
    Address: Address{
        City:    "New York",
        State:   "NY",
        Country: "USA",
    },
}

fmt.Println(e.Address.City)  // Outputs: New York

6. Comparing Structs

Structs are comparable if their fields are comparable. They can be compared using == or != operators.

p1 := Person{"Eve", "Brown", 35}
p2 := Person{"Eve", "Brown", 35}

fmt.Println(p1 == p2)  // Outputs: true

7. Embedded (or Anonymous) Fields

In Go, you can embed one struct into another. This provides a mechanism similar to inheritance in other languages.

type Address struct {
    City, State string
}

type Person struct {
    Name   string
    Address  // Embedded struct
}

p := Person{
    Name:   "Frank",
    Address: Address{
        City:  "Los Angeles",
        State: "CA",
    },
}

fmt.Println(p.City)  // Outputs: Los Angeles

Key Takeaways:

  • Structs allow you to group together fields of possibly different data types.
  • Access or modify struct fields using the dot (.) operator.
  • Structs support nesting, and they can also embed other structs as anonymous fields, providing a mechanism akin to inheritance.
  • Structs are comparable if their fields are.

Structs are a fundamental aspect of Go's type system, enabling you to create custom types that model the shape and behavior of your data.

  1. Structs and methods in Golang:

    In Go, you can define methods for structs. Methods with pointer receivers can modify the original struct.

    package main
    
    import "fmt"
    
    type Rectangle struct {
        Width, Height float64
    }
    
    // Method with value receiver
    func (r Rectangle) Area() float64 {
        return r.Width * r.Height
    }
    
    // Method with pointer receiver
    func (r *Rectangle) Scale(factor float64) {
        r.Width *= factor
        r.Height *= factor
    }
    
    func main() {
        rect := Rectangle{Width: 5, Height: 3}
        fmt.Println(rect.Area()) // 15.0
    
        rect.Scale(2)
        fmt.Println(rect.Area()) // 30.0
    }
    
  2. Golang struct initialization:

    You can initialize a struct using the field names and values or by providing values in order.

    type Person struct {
        Name string
        Age  int
    }
    
    // Initialization with field names
    person1 := Person{Name: "Alice", Age: 25}
    
    // Initialization without field names
    person2 := Person{"Bob", 30}
    
  3. Embedded structs in Golang:

    Embedding allows a struct to include another struct, gaining access to its fields and methods.

    type Address struct {
        City, Country string
    }
    
    type Person struct {
        Name    string
        Age     int
        Address // Embedded struct
    }
    
    person := Person{Name: "John", Age: 30, Address: Address{City: "New York", Country: "USA"}}
    
  4. Struct composition in Golang:

    Struct composition involves creating a new struct by combining existing structs, allowing for modular design.

    type Address struct {
        City, Country string
    }
    
    type Contact struct {
        Email, Phone string
    }
    
    type Person struct {
        Name    string
        Age     int
        Address // Embedded struct
        Contact // Embedded struct
    }
    
    person := Person{Name: "John", Age: 30, Address: Address{City: "New York", Country: "USA"}, Contact: Contact{Email: "john@example.com", Phone: "123-456"}}
    
  5. JSON encoding/decoding with Golang structs:

    Go provides built-in support for encoding and decoding JSON using struct tags.

    import (
        "encoding/json"
        "fmt"
    )
    
    type Person struct {
        Name string `json:"name"`
        Age  int    `json:"age"`
    }
    
    func main() {
        // Encoding to JSON
        person := Person{Name: "Alice", Age: 25}
        jsonBytes, _ := json.Marshal(person)
        fmt.Println(string(jsonBytes))
    
        // Decoding from JSON
        var decodedPerson Person
        json.Unmarshal(jsonBytes, &decodedPerson)
        fmt.Println(decodedPerson)
    }
    
  6. Golang struct tags:

    Struct tags are annotations added to struct fields to provide metadata, often used in encoding and decoding scenarios.

    type Person struct {
        Name string `json:"name"`
        Age  int    `json:"age"`
    }
    
  7. Pointer receivers vs value receivers in Golang structs:

    Methods with pointer receivers can modify the original struct, while methods with value receivers work on a copy.

    type Rectangle struct {
        Width, Height float64
    }
    
    // Method with value receiver
    func (r Rectangle) Area() float64 {
        return r.Width * r.Height
    }
    
    // Method with pointer receiver
    func (r *Rectangle) Scale(factor float64) {
        r.Width *= factor
        r.Height *= factor
    }
    
  8. Anonymous structs in Golang:

    Anonymous structs are structs without a predefined name, useful for short-lived data structures.

    person := struct {
        Name string
        Age  int
    }{
        Name: "Anonymous",
        Age:  30,
    }