Skip to main content
Go Language Fundamentals for Beginners to Advanced
CHAPTER 15 Beginner

Methods and Interfaces

Updated: May 17, 2026
5 min read

# CHAPTER 15

Methods and Interfaces

1. Introduction

In the last chapter, we created Structs to hold data. But in Object-Oriented Programming, objects should also perform actions. A User struct should have a Login() action. In Go, we don't put functions *inside* the struct. Instead, we use Receiver Functions to attach external methods to structs. Furthermore, Go's Interfaces provide a brilliant, implicit way to achieve Polymorphism without strict inheritance.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Define Methods using Receiver Functions.
  • Understand Value Receivers vs Pointer Receivers.
  • Define an Interface.
  • Understand implicit Interface implementation.
  • Use Interfaces to achieve Polymorphism.

3. Methods (Receiver Functions)

A method is simply a normal function with a special "Receiver" argument placed between the func keyword and the function name.
go
12345678910111213141516171819
package main
import "fmt"

type Circle struct {
    Radius float64
}

// Method with a Receiver of type Circle
// 'c' is the variable name representing the specific struct instance
func (c Circle) Area() float64 {
    return 3.14159 * c.Radius * c.Radius
}

func main() {
    myCircle := Circle{Radius: 5}
    
    // We call the method using dot notation!
    fmt.Println("Area:", myCircle.Area()) 
}

4. Value vs Pointer Receivers (CRITICAL)

  • Value Receiver (func (c Circle)): The method receives a *copy* of the struct. If the method changes a field, the original struct is NOT modified.
  • Pointer Receiver (func (c *Circle)): The method receives a *pointer* to the struct. The method CAN modify the original struct.

*Rule of Thumb: Almost always use Pointer Receivers.*

go
123456789101112131415
type User struct {
    Name string
    Age  int
}

// Pointer Receiver: Can modify the original User
func (u *User) HaveBirthday() {
    u.Age++ 
}

func main() {
    u := User{Name: "Alice", Age: 20}
    u.HaveBirthday()
    fmt.Println(u.Age) // Prints 21! 
}

5. Interfaces (The Magic of Go)

An Interface is a completely abstract contract. It defines a set of methods that a type *must* have. In Java/C#, a class must explicitly state implements IAnimal. In Go, Interfaces are implemented IMPLICITLY. If a struct has all the methods required by an interface, it automatically implements that interface!
go
123456789101112131415161718192021222324252627
// 1. Define the Interface
type Animal interface {
    Speak() string
}

// 2. Create Structs
type Dog struct{}
type Cat struct{}

// 3. Attach Methods
func (d Dog) Speak() string { return "Woof!" }
func (c Cat) Speak() string { return "Meow!" }

// 4. Polymorphism in Action
// This function accepts ANY struct that implements the Animal interface
func MakeSound(a Animal) {
    fmt.Println(a.Speak())
}

func main() {
    d := Dog{}
    c := Cat{}

    // Both can be passed into MakeSound because both have a Speak() method!
    MakeSound(d) 
    MakeSound(c) 
}

6. The Empty Interface interface{}

What if you want a function to accept *literally any* data type? You use the empty interface: interface{}. Because the empty interface requires zero methods, *every* data type in Go implements it automatically!
go
1234
// Accepts int, string, struct, anything!
func PrintAnything(v interface{}) {
    fmt.Println("You passed:", v)
}

*(Note: In modern Go 1.18+, the keyword any was introduced as an exact alias for interface{} to make code cleaner).*

7. Common Mistakes

  • Mixing Value and Pointer Receivers: If you use a Pointer Receiver for one method of a struct, you should use Pointer Receivers for ALL methods of that struct to maintain consistency.
  • Overusing Interfaces: Don't create interfaces for everything. Go philosophy: "Return concrete types, accept interfaces." Only create an interface when you actually have multiple different structs that need to be passed into the same function.

8. Best Practices

  • Keep Interfaces Small: In Go, the best interfaces have only 1 or 2 methods. The standard library is full of tiny interfaces like Reader (has 1 method) and Writer (has 1 method).

9. Exercises

  1. 1. Create a Rectangle struct with Width and Height.
  1. 2. Create a Pointer Receiver method Scale(factor int) that multiplies the width and height by the factor.
  1. 3. Call it in main() and print the new dimensions.

10. MCQs with Answers & Explanations

Question 1

How do you attach a method to a struct in Go?

Q2. If a method needs to modify the fields of its struct, what type of receiver must it use? a) A Value Receiver b) A Pointer Receiver Answer: b) A Pointer Receiver. *Explanation: Passing by value only modifies a copy.*
Question 3

How is a Go Interface different from a Java/C# Interface?

Q4. If a struct has all the methods defined in an Interface, does it implement the interface? a) Yes, automatically b) No, it must declare it Answer: a) Yes, automatically.
Question 5

What does the Empty Interface interface{} represent?

Question 6

What new keyword in Go 1.18+ acts as an alias for interface{}?

Q7. Is it good practice to create massive interfaces with 20 methods in Go? a) Yes b) No, Go philosophy heavily favors tiny, 1-method interfaces Answer: b) No.
Question 8

What feature of OOP is achieved by passing different structs (like Dog and Cat) into a function expecting an Animal interface?

Q9. Can an interface contain method bodies (implementation code)? a) Yes b) No Answer: b) No. *Explanation: Interfaces only contain method signatures.*
Question 10

How do you call a method Drive() on an instantiated Car struct named myCar?

11. Interview Preparation

Interview Questions:
  1. 1. Explain the difference between a Value Receiver and a Pointer Receiver. When would you use each?
  1. 2. How does Go achieve Polymorphism without Inheritance?
  1. 3. What is an Empty Interface, and what is the modern alias for it?

12. Summary

Go's approach to OOP is brilliantly simple. You separate the data (Structs) from the actions (Methods via Receivers). By utilizing Pointer Receivers, you ensure memory efficiency and mutability. Finally, Go's implicit Interface system allows for highly flexible, decoupled code, letting you write functions that don't care *what* an object is, only *what it can do*.

13. Next Chapter Recommendation

With data and logic in place, what happens when things go wrong? Go handles errors completely differently than Java or Python. In Chapter 16: Error Handling in Go, we will learn why there is no try/catch and how to build robust, crash-proof applications.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·