Go语言从入门到精通——结构体(struct)——方法

方法

  Go 语言中的方法(Method)是一种作用于特定类型变量的函数。这种特定类型变量叫做接收器(Receiver)。

  如果将特定类型理解为结构体或者"类"时,接收器的概念就类似于其他语言中的 this 或 self。

  在 Go 语言中,接收器的类型可以是任何类型,不仅仅是结构体,任何类型都可以拥有方法。

1
提示:在面向对象的语言中,类拥有的方法一般被理解为类可以做的事情。在 Go 语言中 "方法" 的概念与其他语言一致,只是 Go 语言建立 "接收器" 强调方法的作用对象是接收器,也就是类的实例,而函数没有作用对象。

一、为结构体添加方法

  本节中,将会使用背包作为“对象”,将物品放入背包的过程作为“方法”,通过面向过程的方式和 Go 语言中结构体的方式来理解 “方法” 的概念。

1、面向过程实现方法

  面向过程中没有 "方法" 概念,只能通过结构体和函数,由使用者使用函数参数和调用关系来形成接近 “方法” 的概念,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main
 
type Bag struct {
    items []int
}
 
//将一个物品放入背包的过程
func Insert(b *Bag, itemid int){
    b.items = append(b.items, itemid)
}
 
func main(){
    bag := new(Bag)
    Insert(bag, 1001)
}

2、Go语言的结构体方法

  将背包及放入背包的物品中使用 Go 语言的结构体和方法方式编写: 为 *Bag 创建一个方法,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
 
type Bag struct {
    items []int
}
 
func (b *Bag) Insert(itemid int) {
    b.items = append(b.items, itemid)
}
 
func main() {
    bag := new(Bag)
    bag.Insert(1001)
}

二、接收器——方法作用的目标

  接收器的格式如下:

1
2
3
func (接收器变量 接收器类型) 方法名(参数列表)(返回参数){
    函数体
}
  • 接收器变量:接收器中的参数变量名在命名时,官方建议使用接收器类型名的第一个小写字母,而不是 self、this 之类的命名。
  • 接收器类型:接收器类型和参数类似,可以是指针类型和非指针类型。
  • 方法名、参数列表、返回参数:格式与函数定义一致。

  接收器根据接收器的类型可以分为指针接收器、非指针接收器。两种接收器在使用时会产生不同的效果。根据效果的不同,两种接收器会被用于不同性能和功能要求的代码中。

1、理解指针类型的接收器

  指针类型的接收器由一个结构体的指针组成,更接近于面向对象的 this 或者 self。

  由于指针的特性,调用方法时,修改接收器指针的任意成员变量,在方法结束后,修改都是有效的。

  在下面的例子,使用结构体定义一个属性(Property),为属性添加 SetValue() 方法以封装设置属性的过程,通过属性的 Value() 方法可以重新获得属性的数值。使用属性时,通过 SetValue() 方法的调用,可以达成修改属性值的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main
 
import "fmt"
 
type Property struct {
    value int //属性值
}
 
func (p *Property) SetValue(v int) {
    //修改 p 成员的变量
    p.value = v
}
 
//取属性值
func (p *Property) Value() int {
    return p.value
}
 
func main() {
 
    //实例化属性
    p := new(Property)
 
    //设置值
    p.SetValue(100)
 
    //打印值
    fmt.Println(p.Value())
}

2、理解非指针类型的接收器

  当方法作用于非指针接收器时,Go 语言会在代码运行时将接收器的值复制一份。在非指针接收器的方法中,可以获取接收器的成员值,但修改后无效。

  点(Point)使用结构体描述时,为点添加 Add() 方法,这个方法不能修改 Point 的成员 X、Y 变量,而是在计算后返回新的 Point 对象。Point 属于小内存对象,在函数返回值的复制过程中可以极大地提高代码运行效率,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main
 
import "fmt"
 
//定义点结构
type Point struct {
    X int
    Y int
}
 
//非指针接收器的加方法
func (p Point) Add(other Point) Point {
 
    //成员值与参数相加后返回新的结构
    return Point{p.X + other.X, p.Y + other.Y}
}
 
func main() {
 
    //初始化点
    p1 := Point{1, 1}
    fmt.Println("p1:", p1)
    p2 := Point{2, 2}
    fmt.Println("p2:", p2)
 
    //与另外一个点相加
    result := p1.Add(p2)
 
    //输出结果
    fmt.Println(result)
}

代码输出如下:

1
2
3
4
5
6
7
8
9
Starting: D:\go-testfiles\bin\dlv.exe dap --check-go-version=false --listen=127.0.0.1:64099 from d:\go-testfiles
DAP server listening at: 127.0.0.1:64099
Type 'dlv help' for list of commands.
p1: {1 1}
p2: {2 2}
{3 3}
Process 6084 has exited with status 0
Detaching
dlv dap (13064) exited with code: 0

3、指针和非指针接收器的作用

  在计算机中,小对象由于值复制时的速度较快,所以适合使用非指针接收器。大对象因为复制性能较低,适合使用指针接收器,在接收器和参数间传递时不进行复制,只传递指针。

posted @   左扬  阅读(435)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
levels of contents
点击右上角即可分享
微信分享提示