脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - golang值接收者和指针接收者的区别介绍

golang值接收者和指针接收者的区别介绍

2022-08-30 09:11蔡蔡217 Golang

这篇文章主要介绍了golang值接收者和指针接收者的区别,它和函数的区别在于方法有一个接收者,给一个函数添加一个接收者,那么它就变成了方法,接收者可以是值接收者,也可以是指针接收者,本文通过实例代码介绍的非常详细

方法

方法能给用户自定义的类型添加新的行为。它和函数的区别在于方法有一个接收者,给一个函数添加一个接收者,那么它就变成了方法。接收者可以是值接收者,也可以是指针接收者
在调用方法的时候,值类型既可以调用值接收者的方法,也可以调用指针接收者的方法;指针类型既可以调用指针接收者的方法,也可以调用值接收者的方法。

?
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
32
33
34
35
36
37
38
39
package main
import "fmt"
type Person struct {
    age int
}
func (p Person) AddAge() {
    p.age += 1
}
 
func (p *Person) GetAge() {
    p.age += 1
}
 
func main() {
    // p1 是值类型
    p := Person{age: 18}
    // 值类型 调用接收者也是值类型的方法
    p.AddAge()
    fmt.Println(p.age)
 
    // ----------------------
 
    // p2 是指针类型  指针类型调用接收者是值类型的方法
    p2 := &Person{age: 100}
    p2.AddAge()
    fmt.Println(p2.age)
    //值类型 调用接收者也是指针类型的方法
    p3 := Person{age: 18}
    p3.GetAge()
    fmt.Println(p3.age)
    // 指针类型 调用收者也是指针类型的方法
    p4 := Person{age: 100}
    p4.GetAge()
    fmt.Println(p4.age)
}
//18
//100
//19
//101
值接收者 指针接收者
值类型调用者 传递一个副本 使用值的引用来调用方法
指针类型调用者 传递一个副本 方法里的操作会影响到调用者,类似于指针传参,拷贝了一份指针

总结:
1.一个结构体的方法的接收者可能是类型值或指针
2.当接受者不是一个指针时,该方法操作对应接受者的值的副本,即使你使用了指针调用函数,但是函数的接受者是值类型,所以函数内部操作还是对副本的操作,而不是指针操作。
3.如果接收者是指针,则调用者修改的是指针指向的值本身。

接口实现

当结构体实现一个接口时,可以在方法中设置一个接收者,比如对于以下接口:

?
1
2
3
type Inter interface {
    foo()
}

结构体在实现它时,方法的接收者类型可以是:值、指针。比如:

?
1
2
3
4
type S struct {}
 
func (s S) foo() {} // 值类型
func (s *S) foo() {} // 或者指针类型

在使用结构体初始化接口变量时,结构体的类型也可以是:值、指针。比如:

?
1
2
3
4
5
6
//赋值
var s Inter = S{} // 值类型
s.foo()
 
var s Inter = &S{} // 指针类型
s.foo()

那么调用接口方法的组合实际有四种情况:
值类型结构体 -> 赋值给接口 -> 调用接收者类型为值类型的结构体方法
指针类型结构体 -> 赋值给接口 -> 调用接收者类型为指针类型的结构体方法
值类型结构体 -> 赋值给接口 -> 调用接收者类型为指针类型的结构体方法(不通过)
指针类型结构体 -> 赋值给接口 -> 调用接收者类型为值类型的结构体方法

结构体类型为值类型、调用了接收者为指针的方法不通过。但是反过来,结构体为指针类型时,却可以调用接收值为值或指针的任何方法。这是为什么呢?

接收者是方法的一个额外的参数,而 Go 在调用函数的时候,参数都是值传递的。将一个指针拷贝,它们还是指向同一个地址,指向一个确定的结构体;将一个值拷贝,它们变成了两个不同的结构体,有着不同的地址。这会导致以下两种情况:

当在一个结构体指针上,通过接口,调用一个接收者为值类型的方法时,Go 首先会创建这个指针的副本,然后将这个指针解引用,再作为接收者参数传递给该方法。这两个指针指向相同的地址,所以它们传递给方法的接收者参数都是相同的。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
type Inter interface {
    foo()
}
type S struct {}
func (s S) foo() {} // 接收者为值类型的方法
 
var a Inter = &S{} // 使用结构体指针初始化一个接口
a.foo() // 调用 foo 方法
 
// 实际上底层是这样的:
// 首先拷贝 a 的底层值,即 `&S{}`,是一个结构体指针:
var b *S = a.inner_value // a、b 是不同的变量,但是指向同一个结构体
// 然后将 b 解引用,传递给 foo:
foo(*b) // *b 和 *(a.inner_value) 其实都表示同一个结构体

这些规则用来说明是否我们一个类型的值或者指针实现了该接口:

  • 类型 *T 的可调用方法集包含接受者为 *T 或 T 的所有方法集
  • 类型 T 的可调用方法集包含接受者为 T 的所有方法

两者分别在何时使用

如果方法的接收者是值类型,无论调用者是对象还是对象指针,修改的都是对象的副本,不影响调用者;如果方法的接收者是指针类型,则调用者修改的是指针指向的对象本身

使用指针作为方法的接收者的理由:

  • 方法能够修改接收者指向的值。
  • 避免在每次调用方法时复制该值,在值的类型为大型结构体时,这样做会更加高效。
  • 是使用值接收者还是指针接收者,不是由该方法是否修改了调用者(也就是接收者)来决定,而是应该基于该类型的本质。

到此这篇关于golang值接收者和指针接收者的区别的文章就介绍到这了,更多相关golang值接收者和指针接收者内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/weixin_42128977/article/details/126511071

延伸 · 阅读

精彩推荐
  • GolangGo语言集成开发环境之VS Code安装使用

    Go语言集成开发环境之VS Code安装使用

    VS Code是微软开源的一款编辑器,插件系统十分的丰富,下面介绍如何用VS Code搭建go语言开发环境,需要的朋友可以参考下...

    RandySun11452021-11-21
  • Golang一文了解Go语言中的函数与方法的用法

    一文了解Go语言中的函数与方法的用法

    与大部分语言一致,Go语言中的函数与方法定义与其他语言基本一致,但也有一定的差别。本文将通过示例详细讲讲Go语言中函数与方法的用法,感兴趣的可...

    孙琦Ray6842022-07-05
  • Golanggolang实现sql结果集以json格式输出的方法

    golang实现sql结果集以json格式输出的方法

    这篇文章主要介绍了golang实现sql结果集以json格式输出的方法,涉及Go语言针对sql结果集的遍历、转换及json格式相关操作技巧,需要的朋友可以参考下 ...

    newjueqi4772020-05-06
  • GolangGolang操作excel的方法

    Golang操作excel的方法

    这篇文章主要介绍了Golang操作excel的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    平也的技术博7832021-01-02
  • GolangGO必知必会的常见面试题汇总

    GO必知必会的常见面试题汇总

    这篇文章主要为大家介绍了GO必知必会的常见面试题汇总,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪...

    王中阳Go6792022-08-16
  • GolangGo语言defer语句的三种机制整理

    Go语言defer语句的三种机制整理

    在本篇文章里小编给大家分享的是一篇关于Go语言defer语句的三种机制整理,需要的朋友们学习下吧。 ...

    面向人生编程4692020-06-06
  • Golang使用dep 配置golang 开发环境的操作方法

    使用dep 配置golang 开发环境的操作方法

    下面小编就为大家带来一篇使用dep 配置golang 开发环境的操作方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    jingxian2592020-05-08
  • Golanggolang gorm多条件筛选查询操作

    golang gorm多条件筛选查询操作

    这篇文章主要介绍了golang gorm多条件筛选查询操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 ...

    疯狂的鸭血12172021-03-09