Structs, Methods, and Enums in Go
Structs
Structs are composite types that group together fields of different types.
Defining and Using Structs
type Person struct {
Name string
Age int
}
// Create an instance of a struct
p := Person{Name: "John", Age: 25}
fmt.Println(p) // Output: {John 25}
// Access or modify fields
fmt.Println(p.Name) // Output: John
p.Age = 26
fmt.Println(p.Age) // Output: 26
Anonymous Structs
You can define structs without giving them a name.
emp := struct {
ID int
Role string
}{ID: 101, Role: "Developer"}
fmt.Println(emp) // Output: {101 Developer}
Methods
A method is a function with a receiver, enabling you to associate behavior with structs.
Defining Methods
type Circle struct {
Radius float64
}
// Method with a value receiver
func (c Circle) Area() float64 {
return 3.14 * c.Radius * c.Radius
}
// Method with a pointer receiver
func (c *Circle) SetRadius(r float64) {
c.Radius = r
}
Using Methods
c := Circle{Radius: 5}
// Call a value receiver method
fmt.Println(c.Area()) // Output: 78.5
// Call a pointer receiver method
c.SetRadius(10)
fmt.Println(c.Area()) // Output: 314
Pointer vs. Value Receivers
- Value Receiver: A copy of the struct is passed, and changes don't affect the original struct.
- Pointer Receiver: A pointer to the struct is passed, allowing modifications to the original struct.
Enums (using iota)
Go doesnβt have a native enum
type, but you can mimic enums using const
and iota
.
iota
is a special constant that starts at 0 and increments by 1 for each new constant.- Itβs common to use
iota
withconst
to define a set of related constants.
Basic Enum-like Behavior
type Status int
const (
Pending Status = iota
Approved
Rejected
)
// Usage
status := Pending
fmt.Println(status) // Output: 0
if status == Pending {
fmt.Println("Status is pending.")
}
Custom String Representation for Enums
You can add a String
method to your custom enum type.
func (s Status) String() string {
return [...]string{"Pending", "Approved", "Rejected"}[s]
}
// Usage
fmt.Println(Pending) // Output: Pending
fmt.Println(Approved) // Output: Approved
Combining Structs, Methods, and Enums
Hereβs an example bringing everything together:
type Task struct {
ID int
Title string
Status Status
}
func (t Task) Display() {
fmt.Printf("Task #%d: %s - %s\n", t.ID, t.Title, t.Status)
}
func (t *Task) UpdateStatus(newStatus Status) {
t.Status = newStatus
}
// Usage
func main() {
task := Task{ID: 1, Title: "Write Go notes", Status: Pending}
task.Display() // Output: Task #1: Write Go notes - Pending
task.UpdateStatus(Approved)
task.Display() // Output: Task #1: Write Go notes - Approved
}
Key Points
- Structs: Use to group related data.
- Methods: Add behavior to structs. Use pointer receivers when you need to modify the struct.
- Enums: Mimic enums with
const
andiota
. Add string representations for better readability.