【GO高级编程】02.GO接收者概述

✅ 一、什么是接收者?

在 Go 中,没有类(class)和对象(object)的概念 ,但可以通过 struct方法(method) 实现类似面向对象的功能。

而"接收者"就是用来定义:"这个方法是谁的"。

🔹 语法结构:

复制代码
func (接收者变量 接收者类型) 方法名(参数列表) 返回值 {
    // 方法体
}

例如:

复制代码
type Dog struct {
    Name string
}

// 这里的 `d *Dog` 就是接收者
func (d *Dog) Bark() {
    fmt.Println(d.Name, "在叫:汪汪!")
}
  • d:接收者变量名(你可以叫它 dog, t, self 等)
  • *Dog:接收者类型(可以是指针或值)
  • Bark():方法名

调用时:

复制代码
dog := &Dog{Name: "旺财"}
dog.Bark() // 输出:旺财 在叫:汪汪!

✅ 二、接收者的两种形式

|----------|------------|--------------|
| 类型 | 写法 | 含义 |
| 🟢 值接收者 | (d Dog) | 方法操作的是该类型的副本 |
| 🔵 指针接收者 | (d *Dog) | 方法操作的是原始对象本身 |

示例对比:

复制代码
type Person struct {
    Name string
}

// 值接收者:只能读,不能改原对象
func (p Person) SetNameByValue(name string) {
    p.Name = name // 修改的是副本!
}

// 指针接收者:可以直接修改原对象
func (p *Person) SetNameByPointer(name string) {
    p.Name = name // 真正修改了原对象
}

测试代码:

复制代码
go

编辑


func main() {
    person := Person{Name: "小明"}

    person.SetNameByValue("小红")
    fmt.Println(person.Name) // 输出:小明 ❌ 没变!

    person.SetNameByPointer("小蓝")
    fmt.Println(person.Name) // 输出:小蓝 ✅ 改了!
}

💡 因为值接收者传入的是拷贝,所以改不动原数据。


✅ 三、为什么需要接收者?

Go 不像 Java/C++ 那样有 thisself 关键字。接收者的作用就是:

  • 明确指定某个方法属于哪个类型
  • 让该类型的所有实例都可以调用这个方法
  • 实现"封装"和"多态"

就像你说"狗会叫",那么 Bark() 方法就应该属于 Dog 类型。


✅ 四、接收者的常见写法风格

复制代码
go

编辑


func (d Dog) Eat()        {} // d 是 Dog 的一个副本
func (d *Dog) Run()       {} // d 是指向 Dog 的指针
func (p *Person) GetName() string { return p.Name }

命名建议:

  • 单个字母即可,如 d, p, s
  • 一般用类型首字母小写,比如 dog, person(dog *Dog)
  • 不要用 selfthis(不是 Python/JavaScript)

✅ 五、自动解引用机制(重要!)

Go 很智能,允许你混用:

复制代码
go

编辑


dog := Dog{Name: "花花"}
ptr := &dog

dog.Run() // Run 是 *Dog 方法?没关系,Go 自动转成 (&dog).Run()
ptr.Eat() // Eat 是 Dog 方法?也没关系,Go 自动转成 (*ptr).Eat()

✅ 所以你在调用方法时,不用关心它是值接收者还是指针接收者,Go 会自动处理。

⚠️ 但在 接口赋值 时就有区别了(见下文)。


✅ 六、接收者与接口的关系(关键!)

假设你有一个接口:

复制代码
go

编辑


type Animal interface {
    Move()
}

如果你这样实现:

复制代码
go

编辑


func (a *AnimalImpl) Move() {}

那么只有 *AnimalImpl 实现了接口,AnimalImpl 本身没有实现!

所以以下代码会报错:

复制代码
go

编辑


var a Animal = AnimalImpl{} // ❌ 错误!AnimalImpl 没有实现 Move()

正确写法:

复制代码
go

编辑


var a Animal = &AnimalImpl{} // ✅ 正确

👉 因此:如果要用类型实现接口,推荐统一使用指针接收者


✅ 七、什么时候用值接收者?什么时候用指针接收者?

|-----------------|----------------|
| 场景 | 推荐 |
| 方法要修改字段 | ✅ 必须用指针接收者 |
| 结构体较大(> 几十个字节) | ✅ 用指针接收者(避免拷贝) |
| 只读操作、小型结构体 | 可用值接收者 |
| 实现接口 | 推荐用指针接收者 |
| 不确定时 | 用指针接收者更安全 |


✅ 总结

|-------------------------|------------------------------------------|
| 问题 | 回答 |
| 什么是接收者? | 定义"这个方法是谁的"的语法结构 |
| 写法是什么? | func (变量 类型) 方法名(...) |
| ***** 和不加的区别? | 是否能修改原对象、是否拷贝数据 |
| 应该用哪个? | 修改字段 → 用 *T ;只读 → 可用 T ;接口 → 推荐 *T |
| 为什么重要? | 是 Go 实现"面向对象"的核心机制之一 |

💡 一句话记住

接收者就是 Go 的 thisself,它让方法和类型绑定在一起,形成"行为 + 数据"的组合。

你现在完全可以把接收者理解为:"我是这个类型的成员函数"。

相关推荐
Aotman_2 小时前
JavaScript去除对象字段空格
开发语言·前端·javascript
云和数据.ChenGuang2 小时前
Zabbix 6 与 PHP 5 版本**完全不兼容
运维·开发语言·php·zabbix·运维工程师
csbysj20202 小时前
Ruby 范围(Range)
开发语言
听风吟丶2 小时前
Spring Boot 自动配置原理深度解析与实战
java·spring boot·后端
苏 凉2 小时前
在 openEuler 24.03 LTS SP2 上安装部署 iSula 容器引擎及性能测试
开发语言·rust
bing.shao2 小时前
Golang 之闭包
java·算法·golang
qq_336313932 小时前
HashMap
java·开发语言
专注VB编程开发20年2 小时前
C# int*指向 int 的指针类型(unsafe 上下文)
java·开发语言·c#
计算机学姐2 小时前
基于SSM的生鲜食品商城系统【2026最新】
java·vue.js·后端·mysql·java-ee·tomcat·mybatis