Golang Tutorial

Fundamentals

Control Statements

Functions & Methods

Structure

Arrays & Slices

String

Pointers

Interfaces

Concurrency

Pointer to Struct in Golang

In Go, structures (often just called structs) are composite data types that group together variables of different data types under a single type name. Pointers to structs are often used to save memory or to allow a function to modify the struct directly.

Here's a basic tutorial on using pointers to structs in Go:

1. Declaring a Pointer to a Struct

Let's start with a simple Person struct and declare a pointer to it:

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func main() {
    var p1 Person = Person{"Alice", 30}
    var ptr *Person = &p1
    fmt.Println(ptr)  // This will print the memory address of p1
}

2. Accessing Struct Fields via a Pointer

To access the fields of a struct through a pointer, you can use the -> operator in languages like C, but in Go, you simply use the . operator:

fmt.Println(ptr.Name)  // Prints "Alice"

3. Modifying Struct Fields via a Pointer

Just as you accessed the fields, you can also modify them:

ptr.Age = 31
fmt.Println(p1.Age)  // Prints 31, since ptr is pointing to p1

4. Using Functions to Modify Structs

Passing a struct to a function by value (i.e., without using pointers) means the function receives a copy of the struct. Changes to the struct inside the function won't reflect outside the function. To modify the original struct inside a function, you'd pass a pointer to the struct:

func updateAge(p *Person, newAge int) {
    p.Age = newAge
}

func main() {
    var p1 Person = Person{"Bob", 25}
    updateAge(&p1, 26)
    fmt.Println(p1.Age)  // Prints 26, since we passed a pointer to the function
}

5. Creating a New Instance with new()

The built-in new() function can be used to create a new instance of a struct, and it returns a pointer to that struct:

ptr := new(Person)
ptr.Name = "Charlie"
ptr.Age = 28

6. Using Composite Literals with Pointers

You can use composite literals to instantiate a struct and get a pointer to it:

ptr := &Person{"Dave", 40}

Key Takeaways:

  • A pointer to a struct allows direct access to the struct's fields or methods without copying the struct.
  • In Go, you can use the familiar . operator to access or modify struct fields through a pointer, unlike some other languages where a different operator might be required.
  • When passing a struct to a function, if you want the function to modify the original struct, you should pass a pointer to the struct.

Working with pointers requires careful attention to ensure you don't inadvertently modify data you didn't intend to or encounter null pointer errors. Always ensure your pointers are properly initialized before dereferencing them.

  1. Accessing struct fields using pointers in Golang:

    • Description: Pointers to structs in Golang are commonly used to access and modify the fields of a struct directly.

    • Code:

      package main
      
      import "fmt"
      
      // Struct definition
      type Person struct {
          Name string
          Age  int
      }
      
      func main() {
          // Accessing struct fields using pointers
          person := Person{Name: "John Doe", Age: 30}
          personPointer := &person
      
          // Accessing fields using pointers
          fmt.Println("Name:", personPointer.Name)
          fmt.Println("Age:", personPointer.Age)
      
          // Modifying fields using pointers
          personPointer.Age = 31
          fmt.Println("Updated Age:", person.Age)
      }
      
  2. Passing pointers to structs as function parameters in Golang:

    • Description: Pointers to structs can be passed to functions, allowing the function to modify the underlying struct.

    • Code:

      package main
      
      import "fmt"
      
      // Struct definition
      type Person struct {
          Name string
          Age  int
      }
      
      // Function modifying a struct through a pointer
      func modifyPerson(personPointer *Person, newName string, newAge int) {
          personPointer.Name = newName
          personPointer.Age = newAge
      }
      
      func main() {
          // Passing pointers to structs as function parameters
          person := Person{Name: "John Doe", Age: 30}
          modifyPerson(&person, "Jane Doe", 25)
      
          fmt.Println("Modified Person:", person)
      }
      
  3. Working with pointer receivers and methods for structs in Golang:

    • Description: Golang allows methods with pointer receivers, enabling modification of the struct within the method.

    • Code:

      package main
      
      import "fmt"
      
      // Struct definition
      type Counter struct {
          count int
      }
      
      // Method with pointer receiver
      func (c *Counter) increment() {
          c.count++
      }
      
      func main() {
          // Working with pointer receivers and methods for structs
          counter := Counter{count: 0}
          counter.increment()
      
          fmt.Println("Count after increment:", counter.count)
      }
      
  4. Pointer to struct vs struct value in Golang:

    • Description: Understanding the difference between using a pointer to a struct and the struct value is crucial for avoiding unintended side effects.

    • Code:

      package main
      
      import "fmt"
      
      // Struct definition
      type Person struct {
          Name string
          Age  int
      }
      
      // Function with struct value parameter
      func modifyPersonValue(person Person, newName string, newAge int) {
          person.Name = newName
          person.Age = newAge
      }
      
      // Function with pointer to struct parameter
      func modifyPersonPointer(personPointer *Person, newName string, newAge int) {
          personPointer.Name = newName
          personPointer.Age = newAge
      }
      
      func main() {
          // Pointer to struct vs struct value
          person := Person{Name: "John Doe", Age: 30}
      
          // Using struct value
          modifyPersonValue(person, "Jane Doe", 25)
          fmt.Println("Person after modifyPersonValue:", person)
      
          // Using pointer to struct
          modifyPersonPointer(&person, "Bob Smith", 35)
          fmt.Println("Person after modifyPersonPointer:", person)
      }
      
  5. Initializing and modifying structs with pointers in Golang:

    • Description: Pointers to structs allow dynamic initialization and modification of struct fields.

    • Code:

      package main
      
      import "fmt"
      
      // Struct definition
      type Person struct {
          Name string
          Age  int
      }
      
      func main() {
          // Initializing and modifying structs with pointers
          personPointer := new(Person)
          (*personPointer).Name = "John Doe"
          (*personPointer).Age = 30
      
          fmt.Println("Initialized Person:", *personPointer)
      
          // Shortcut for using pointers to structs
          personShortcut := &Person{Name: "Jane Doe", Age: 25}
          fmt.Println("Initialized Person (shortcut):", *personShortcut)
      }
      
  6. Pointer arithmetic with structs in Golang:

    • Description: Golang does not support direct pointer arithmetic with structs. However, pointers to fields can be used to achieve similar effects.

    • Code:

      package main
      
      import "fmt"
      
      // Struct definition
      type Point struct {
          X, Y int
      }
      
      func main() {
          // Pointer arithmetic with structs in Golang
          point := Point{X: 10, Y: 20}
          pointPointer := &point
      
          // Using pointers to fields for "pointer arithmetic"
          xPointer := &pointPointer.X
          yPointer := &pointPointer.Y
      
          *xPointer = *xPointer + 5
          *yPointer = *yPointer - 5
      
          fmt.Println("Modified Point:", point)
      }