Go Receiver Function like Class Method

像 Class Method 的奇特 Go Receiver Function

Go Receiver Function

第一次看到 Go 的 Receiver Function 會覺得這是啥怪語法,函式名前面還能接收參數?

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 語言提倡「Composition over inheritance」(組合優於繼承),並極力追求程式碼的簡潔性,以此迴避 class-based OOP 所帶來的複雜性。因此,Go 並不直接提供繼承機制,而是透過以下三個核心要素,來達到類似 OOP 的模式:

  • Structs: 用於定義資料的結構。
  • Receiver Functions: 用於為自定義類型(包括 struct、基於內建類型的自定義類型等)定義相關聯的方法和行為。
  • Interfaces: 用於實現多型(polymorphism)。

其他語言相同範例

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
}
}

總結

Go 的 Receiver Function 本質上仍然是一個獨立的函式,它只是透過特殊的語法,將該函式「綁定」到一個特定的型別上,使其能夠以物件導向的風格被呼叫。這種設計巧妙地平衡了物件導向的封裝性與 Go 追求的簡潔性。

不過相較於 person.greet("Hi") 我還是更偏好單純函式 greet("Hi", person) 的思考方式。

  • 一個是函式是資料的一部分。
  • 一個是函式資料相互獨立的。

而在撰寫 Go 的思維下兩者各參雜一點,十分奇妙。

延伸閱讀