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

 更新时间:2022年08月29日 16:53:22   作者:蔡蔡217  
这篇文章主要介绍了golang值接收者和指针接收者的区别,它和函数的区别在于方法有一个接收者,给一个函数添加一个接收者,那么它就变成了方法,接收者可以是值接收者,也可以是指针接收者,本文通过实例代码介绍的非常详细,需要的朋友可以参考下

方法

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

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.如果接收者是指针,则调用者修改的是指针指向的值本身。

接口实现

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

type Inter interface {
    foo()
}

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

type S struct {}

func (s S) foo() {} // 值类型
func (s *S) foo() {} // 或者指针类型

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

//赋值
var s Inter = S{} // 值类型
s.foo()

var s Inter = &S{} // 指针类型
s.foo()

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

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

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

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

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值接收者和指针接收者内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 解析golang中的并发安全和锁问题

    解析golang中的并发安全和锁问题

    本文我们来学习一下golang中的并发安全和锁问题,文章通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2021-11-11
  • Golang实现断点续传功能

    Golang实现断点续传功能

    这篇文章主要为大家详细介绍了Golang实现断点续传、复制文件功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • Golang时间及时间戳的获取转换超全面详细讲解

    Golang时间及时间戳的获取转换超全面详细讲解

    说实话,golang的时间转化还是很麻烦的,最起码比php麻烦很多,下面这篇文章主要给大家介绍了关于golang时间/时间戳的获取与转换的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-12-12
  • Golang中禁止拷贝的实现代码

    Golang中禁止拷贝的实现代码

    这篇文章主要给大家介绍了关于Golang中实现禁止拷贝的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • go语言实现简单的并发网页爬虫示例

    go语言实现简单的并发网页爬虫示例

    在这个章节中,我们将会结合之前的知识点,实现一个简易的并发网页爬虫,我们的爬虫会先爬取一个起始页面,提取出所有的链接,然后并发地爬取这些链接,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2023-08-08
  • Golang中的[]byte与16进制(String)之间的转换方式

    Golang中的[]byte与16进制(String)之间的转换方式

    这篇文章主要介绍了Golang中的[]byte与16进制(String)之间的转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • golang并发工具MapReduce降低服务响应时间

    golang并发工具MapReduce降低服务响应时间

    这篇文章主要为大家介绍了golang并发使用MapReduce降低服务响应时间实践使用示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04
  • Go WEB框架使用拦截器验证用户登录状态实现

    Go WEB框架使用拦截器验证用户登录状态实现

    这篇文章主要为大家介绍了Go WEB框架使用拦截器验证用户登录状态实现,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • 利用Go语言搭建WebSocket服务端方法示例

    利用Go语言搭建WebSocket服务端方法示例

    这篇文章主要给大家介绍了利用Go语言搭建WebSocket服务端方法,文中通过示例代码介绍的非常详细,需要的朋友们可以参考借鉴,下面来一起看看吧。
    2017-04-04
  • Go高级特性探究之优先级队列详解

    Go高级特性探究之优先级队列详解

    Heap 是一种数据结构,这种数据结构常用于实现优先队列,这篇文章主要就是来和大家深入探讨一下GO语言中的优先级队列,感兴趣的可以了解一下
    2023-06-06

最新评论