首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
01|前世今生:你不得不了解的Go的历史和现状
02|拒绝“Hello and Bye”:Go语言的设计哲学是怎么一回事?
03|配好环境:选择一种最适合你的Go安装方法
04|初窥门径:一个Go程序的结构是怎样的?
05|标准先行:Go项目的布局标准是什么?
06|构建模式:Go是怎么解决包依赖管理问题的?
07|构建模式:Go Module的6类常规操作
08|入口函数与包初始化:搞清Go程序的执行次序
09|即学即练:构建一个Web服务就是这么简单
10|变量声明:静态语言有别于动态语言的重要特征
11|代码块与作用域:如何保证变量不会被遮蔽?
12|基本数据类型:Go原生支持的数值类型有哪些?
13|基本数据类型:为什么Go要原生支持字符串类型?
14|常量:Go在“常量”设计上的创新有哪些?
15|同构复合类型:从定长数组到变长切片
16|复合数据类型:原生map类型的实现机制是怎样的?
17|复合数据类型:用结构体建立对真实世界的抽象
18|控制结构:if的“快乐路径”原则
19|控制结构:Go的for循环,仅此一种
20|控制结构:Go中的switch语句有哪些变化?
21|函数:请叫我“一等公民”
22|函数:怎么结合多返回值进行错误处理?
23|函数:怎么让函数更简洁健壮?
24|方法:理解“方法”的本质
25|方法:方法集合与如何选择receiver类型?
26|方法:如何用类型嵌入模拟实现“继承”?
27|即学即练:跟踪函数调用链,理解代码更直观
28|接口:接口即契约
29|接口:为什么nil接口不等于nil?
30|接口:Go中最强大的魔法
31|并发:Go的并发方案实现方案是怎样的?
32|并发:聊聊Goroutine调度器的原理
33|并发:小channel中蕴含大智慧
34|并发:如何使用共享变量?
35|即学即练:如何实现一个轻量级线程池?
36|打稳根基:怎么实现一个TCP服务器?(上)
37|代码操练:怎么实现一个TCP服务器?(中)
38|成果优化:怎么实现一个TCP服务器?(下)
39 | 驯服泛型:了解类型参数
40|驯服泛型:定义泛型约束
41 | 驯服泛型:明确使用时机
当前位置:
首页>>
技术小册>>
Go语言入门实战经典
小册名称:Go语言入门实战经典
### 25 | 方法:方法集合与如何选择Receiver类型? 在Go语言的编程世界中,方法是附加到特定类型上的函数,它们允许我们为类型定义行为。这一章将深入探讨Go语言中的方法集合概念,以及在设计程序时如何选择合适的receiver类型。通过理解这些概念,你将能够编写出更加灵活、可维护和可扩展的代码。 #### 一、方法的基本概念 在Go中,方法是一种特殊的函数,它关联到一个类型上。这意味着,当你定义了一个方法,你实际上是给那个类型添加了一个新的行为。方法的定义格式如下: ```go func (receiver ReceiverType) MethodName(parameters) (results) { // 方法体 } ``` 其中,`receiver` 是方法所属的类型的实例,`ReceiverType` 是该实例的类型,`MethodName` 是方法的名称,`parameters` 是方法的参数列表(可选),`results` 是方法的返回结果(可选)。 #### 二、方法集合 方法集合是指与某个类型相关联的所有方法的集合。在Go中,每个类型(无论是自定义类型还是内置类型)都可以有自己的方法集合。方法集合的存在,使得类型不仅仅是数据的容器,还具备了操作这些数据的能力。 ##### 2.1 自定义类型的方法集合 当你定义一个自定义类型时,可以通过为该类型定义方法来扩展其功能。例如,假设我们有一个表示二维点的类型`Point`: ```go type Point struct { X, Y float64 } // Distance 方法计算点到原点的距离 func (p Point) Distance() float64 { return math.Sqrt(p.X*p.X + p.Y*p.Y) } // Scale 方法按给定因子缩放点 func (p Point) Scale(factor float64) Point { return Point{p.X * factor, p.Y * factor} } ``` 在这个例子中,`Point` 类型拥有两个方法:`Distance` 和 `Scale`。这两个方法共同构成了`Point`类型的方法集合。 ##### 2.2 内置类型的方法集合 虽然Go的内置类型(如`int`、`string`等)在标准库中并没有直接定义方法,但你可以通过类型别名(type alias)和接口来间接地为它们添加方法。不过,更常见的做法是通过定义新的类型来封装内置类型,并为其添加方法。 #### 三、如何选择Receiver类型 在设计Go程序时,选择合适的receiver类型对于实现高效、可维护的代码至关重要。Receiver类型可以是值类型(value receiver)或指针类型(pointer receiver),每种类型都有其适用场景。 ##### 3.1 值类型Receiver 当receiver是值类型时,方法接收的是调用者的副本。这意味着在方法内部对receiver的任何修改都不会影响到原始数据。这种方式适用于以下几种情况: - 当方法不需要修改receiver的状态时。 - 当receiver是一个小结构体或基本类型时,复制的成本较低。 ```go type MyInt int func (m MyInt) Add(n MyInt) MyInt { return m + n } ``` 在这个例子中,`Add` 方法不会修改`MyInt`实例的值,因此使用值类型receiver是合适的。 ##### 3.2 指针类型Receiver 当receiver是指针类型时,方法接收的是调用者的地址。这意味着在方法内部对receiver的任何修改都会直接反映到原始数据上。这种方式适用于以下几种情况: - 当方法需要修改receiver的状态时。 - 当receiver是一个大型结构体时,使用指针可以避免不必要的复制,提高效率。 ```go type LargeStruct struct { // 假设这里有很多字段 } func (ls *LargeStruct) Modify() { // 修改LargeStruct的某个字段 } ``` 在这个例子中,由于`LargeStruct`可能包含大量数据,使用指针类型receiver可以避免在每次方法调用时都复制整个结构体。 ##### 3.3 Receiver类型的选择原则 - **如果方法不需要修改receiver的状态,且receiver较小,考虑使用值类型receiver。** - **如果方法需要修改receiver的状态,或者receiver较大,使用指针类型receiver以提高效率。** - **一致性原则:如果类型的一个方法使用了指针类型receiver,那么该类型的所有方法都应该使用指针类型receiver,以保持接口的一致性。** #### 四、方法集合与接口 在Go中,接口是一种类型,它定义了一组方法,但不实现它们。任何实现了这些方法的具体类型都被视为实现了该接口。方法集合与接口的关系非常紧密,因为接口的实现依赖于类型的方法集合。 当你定义了一个接口,并希望某个类型实现该接口时,你需要确保该类型的方法集合中包含了接口定义的所有方法。这样,该类型就被视为实现了该接口,可以赋值给接口类型的变量,从而享受接口带来的多态性和解耦的好处。 #### 五、总结 在Go语言中,方法集合是类型的一个重要组成部分,它定义了类型可以执行的操作。选择合适的receiver类型对于编写高效、可维护的代码至关重要。通过理解方法集合和receiver类型的选择原则,你可以更好地利用Go语言的特性,编写出更加优秀的程序。同时,方法集合与接口的结合使用,为Go语言提供了强大的多态性和解耦能力,使得Go语言在构建大型、复杂的系统时更加得心应手。
上一篇:
24|方法:理解“方法”的本质
下一篇:
26|方法:如何用类型嵌入模拟实现“继承”?
该分类下的相关小册推荐:
go编程权威指南(四)
go编程权威指南(二)
深入浅出Go语言核心编程(五)
Golang并发编程实战
go编程权威指南(一)
Go开发权威指南(上)
Golang修炼指南
深入浅出Go语言核心编程(七)
深入浅出Go语言核心编程(二)
Go-Web编程实战
深入浅出Go语言核心编程(四)
从零写一个基于go语言的Web框架