[Go] Method

Posted August 30, 2021 by clannadzsy  ‐  1 min read

适用环境:两个完整程序分别保存为 main.go,在 Go 1.23.3、Windows/amd64 运行 go run main.go。Go 的结构体嵌入提供方法提升(promotion),并非面向对象语言中的类继承。

嵌入与方法提升

package main

import "fmt"

type Human struct {
    name string
    age int
    phone string
}

type Student struct {
    Human
    school string
}

type Employee struct {
    Human
    company string
}

func (h *Human) SayHi() {
    fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}

func main() {
    mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
    sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}

    mark.SayHi()
    sam.SayHi()
}

第一个程序中,mark.SayHi() 和 sam.SayHi() 使用从嵌入字段提升的方法;变量可寻址,调用时可自动取地址匹配 *Human 接收者。

外层类型的同名方法

package main

import "fmt"

type Human struct {
    name string
    age int
    phone string
}

type Student struct {
    Human
    school string
}

type Employee struct {
    Human
    company string
}

func (h *Human) SayHi() {
    fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}

// Employee 的同名方法会遮蔽通过嵌入字段提升的 SayHi。
func (e *Employee) SayHi() {
    fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
        e.company, e.phone) //Yes you can split into 2 lines here.
}

func main() {
    mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
    sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}

    mark.SayHi()
    sam.SayHi()
}

第二个程序中,sam.SayHi() 调用 *Employee 的方法,而 sam.Human.SayHi() 仍可显式调用嵌入字段的方法。这里没有动态重写 Human 的行为;两次运行应分别看到通用问候和带公司名称的问候。参考 Go 语言规范:结构体嵌入及提升。