Data Structures
Arrays and Slices
Arrays
Arrays in Go are fixed-length sequences of elements of the same type. They are defined with a specific size, and once created, their size cannot be changed.
var a [5]int // array of 5 integers
Arrays are useful when the size of the data is known and fixed, but their static nature makes them less flexible.
Slices
Slices are more flexible than arrays and are the preferred data structure in Go for handling sequences of elements. A slice is a dynamically-sized, flexible view into the elements of an array.
s := []int{1, 2, 3, 4, 5} // slice of integers
Slices provide powerful and convenient ways to work with sequences of data. They support automatic resizing and share the underlying array storage, making them memory-efficient.
Maps
Maps are Go's built-in hash table implementation and are used to store key-value pairs. They provide fast lookups, additions, and deletions.
m := make(map[string]int)
m["foo"] = 42
Maps are ideal for scenarios where you need to associate unique keys with values, such as dictionaries, caches, and lookup tables.
Structs
Structs are composite data types that group together variables under a single name. Each variable in a struct is called a field, and they can be of different types.
type Person struct {
Name string
Age int
}
Structs are the building blocks of data structures in Go and are used to create complex types that group related data together.
Pointers
Understanding Pointers
Pointers hold the memory address of a value. They are used to reference or dereference variables, allowing for indirect manipulation of values.
var p *int
i := 42
p = &i // p now holds the memory address of i
Pointers are crucial for dynamic data structures, performance optimization, and when you need to share data between functions.
Pointer Operations
-
Dereferencing: Access the value at the memory address held by a pointer using the
*
operator.
fmt.Println(*p) // prints the value of i, which is 42
-
Address-of: Get the memory address of a variable using the
&
operator.
p = &i // p now holds the address of i
Structs with Pointers
Pointers can be used with structs to reference and manipulate data without copying the entire struct.
type Person struct {
Name string
Age int
}
p := &Person{"Alice", 30}
p.Age = 31 // modify the Age field through the pointer
Using pointers with structs allows for more efficient memory usage and direct manipulation of the original data.
Methods and Interfaces
Defining Methods
Methods are functions with a special receiver argument. They can be defined for any type (except pointer types) and allow you to associate behaviors with types.
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return 3.14 * c.Radius * c.Radius
}
In the example above, the Area
method is defined for the Circle
type, allowing instances of Circle
to calculate their area.
Receiver Functions
Receiver functions are methods that operate on the receiver, which is a special parameter between the func
keyword and the method name. Receivers can be value receivers or pointer receivers.
-
Value Receiver: The method operates on a copy of the value.
func (c Circle) Area() float64 { return 3.14 * c.Radius * c.Radius }
-
Pointer Receiver: The method operates on the original value through a pointer.
func (c *Circle) Scale(factor float64) { c.Radius *= factor }
Using pointer receivers allows methods to modify the original value and is more efficient for large structs.
Understanding and Using Interfaces
Interfaces define a set of method signatures and are satisfied by any type that implements those methods. They provide a way to specify the behavior that types must have.
type Shape interface {
Area() float64
Perimeter() float64
}
Interfaces enable polymorphism in Go, allowing you to write flexible and reusable code.
Example Usage of Interfaces
type Rectangle struct {
Width, Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
func PrintShapeInfo(s Shape) {
fmt.Println("Area:", s.Area())
fmt.Println("Perimeter:", s.Perimeter())
}
r := Rectangle{Width: 3, Height: 4}
PrintShapeInfo(r)
In this example, the Rectangle
type implements the Shape
interface by providing the Area
and Perimeter
methods. The PrintShapeInfo
function can accept any type that satisfies the Shape
interface, demonstrating the power and flexibility of interfaces in Go.
Top comments (0)