Go Methods

Adding behavior to your Go types

🔧 What are Go Methods?

Go methods are functions with special receiver arguments that allow you to define behavior for custom types. They enable object-oriented programming patterns in Go's simple and elegant way.


// Define a struct
type Person struct {
    Name string
    Age  int
}

// Define a method for Person
func (p Person) Greet() string {
    return "Hello, I'm " + p.Name
}
                                    

Output:

Hello, I'm John

Key Method Concepts

📨

Receiver

The type that receives the method

func (p Person) Method() {}
📋

Value Receiver

Works with a copy of the value

func (p Person) GetName() string
👆

Pointer Receiver

Works with the original value

func (p *Person) SetName(name string)
🎯

Method Set

All methods available to a type

person.Greet()
person.SetAge(25)

🔹 Value vs Pointer Receivers

Understanding when to use value or pointer receivers:

type Counter struct {
    count int
}

// Value receiver - doesn't modify original
func (c Counter) GetCount() int {
    return c.count
}

// Pointer receiver - modifies original
func (c *Counter) Increment() {
    c.count++
}

// Usage
func main() {
    counter := Counter{count: 0}
    
    fmt.Println(counter.GetCount()) // 0
    counter.Increment()
    fmt.Println(counter.GetCount()) // 1
}

Output:

0
1

🔹 Methods on Built-in Types

You can define methods on custom types based on built-in types:

// Custom type based on string
type MyString string

// Method for custom type
func (s MyString) Length() int {
    return len(string(s))
}

func (s MyString) Upper() MyString {
    return MyString(strings.ToUpper(string(s)))
}

// Usage
func main() {
    text := MyString("hello world")
    fmt.Println(text.Length())  // 11
    fmt.Println(text.Upper())   // HELLO WORLD
}

Output:

11
HELLO WORLD

🔹 Method Chaining

Return the receiver to enable method chaining:

type Builder struct {
    text string
}

func (b *Builder) Add(s string) *Builder {
    b.text += s
    return b
}

func (b *Builder) AddSpace() *Builder {
    b.text += " "
    return b
}

func (b *Builder) String() string {
    return b.text
}

// Usage
func main() {
    result := &Builder{}
    final := result.Add("Hello").AddSpace().Add("World").String()
    fmt.Println(final) // Hello World
}

Output:

Hello World

🧠 Test Your Knowledge

When should you use a pointer receiver?