Go Receiver Function like Class Method

Go Receiver Function

The first time you see a Go Receiver Function, you might wonder what this strange syntax is, with parameters accepted before the function name?

type User struct {
name string
}
// receiver function
func (u User) Greet() {
fmt.Println("Hello, my name is", u.name)
}
func main() {
u := User{name: "Riceball"}
u.Greet()
}

Go language advocates for “Composition over inheritance” and pursues code simplicity to avoid the complexities brought by class-based OOP. Therefore, Go does not provide an inheritance mechanism directly but achieves a similar OOP pattern through the following three core elements:

  • Structs: Used to define the structure of data.
  • Receiver Functions (Method): Used to define associated methods for custom types (including structs, custom types based on built-in types, etc.).
  • Interfaces: Used to implement polymorphism.

Examples in Other Languages

JavaScript

const user = {
name: "Riceball",
greet() {
console.log("Hello, my name is", this.name)
}
}
user.greet()

Java

class User {
private String name;
public User(String name) {
this.name = name;
}
public void greet() {
System.out.println("Hello, my name is " + this.name);
}
}
public class Main {
public static void main(String[] args) {
User u = new User("Riceball");
u.greet(); // Hello, my name is Riceball
}
}

Summary

The Go Receiver Function is essentially still an independent function; it just uses special syntax to “bind” the function to a specific type, allowing it to be called in an object-oriented style. This design cleverly balances the encapsulation of object-oriented programming and the simplicity that Go pursues.

However, compared to person.greet("Hi"), I still prefer the pure function way of thinking, greet("Hi", person).

  • One is the function is part of the data.
  • One is the function and data are independent of each other.

In the mindset of writing Go, it’s fascinating how both ways intertwine.

Further Reading