Go 值接收者和指针接收者 区别

首先回顾一下Go语言值类型和指针类型直接调用其值接收者方法和指针接收者方法的区别:

先看一个实例:

package main

import "fmt"

type I interface {
	Get() int
	Set(int)
}

type S struct {
	Age int
}

func(s S) Get()int {
	return s.Age
}

func(s *S) Set(age int) {
	s.Age = age
}

func main() {
	s1 := S{}
	fmt.Printf("s1:%d\n",s1.Get())
	s1.Set(20)
	fmt.Printf("s1:%d\n",s1.Get())

	s2 := &S{}
	fmt.Printf("s2:%d\n",s2.Get())
	s2.Set(20)
	fmt.Printf("s2:%d\n",s2.Get())
}

上面例子输出:

之所以值类型变量和指针类型变量都可以调用其值接收者方法和指针接收者方法,仅仅是Go语言的语法糖在起作用。

值接收者声明的方法,调用时会使用这个值的一个副本去执行,而指针接收者在调用者会共享调用方法时接收者所指向的值,即可以修改指向的值。

接下来我们主要说明值接收者和指针接收者赋值给接口的区别:

先看一个实例:

package main

import "fmt"

type I interface {
	Get() int
	Set(int)
}

type S struct {
	Age int
}

func(s S) Get()int {
	return s.Age
}

func(s *S) Set(age int) {
	s.Age = age
}

func main() {
	var s I  = &S{}
	fmt.Printf("%d\n",s.Get())
	s.Set(20)
	fmt.Printf("%d\n",s.Get())
}

上面例子输出:

但是把23行改为:

var s I  = S{}

编译将报错:

大致意思就是:S没有实现Set函数,就没有实现接口I,所以不能赋值。

表面上看*S也没有实现Get函数,但是*S所指向的值实现了Get函数,所以*S也自动拥有Get函数,所以实现接口I。S作为值接收者,Go无从知道值的原始值是什么,因为 值接收者 是份拷贝,所以不能影响S。go 会把指针进行隐式转换得到 value,但反过来则不行

所以,类型 T 变量只有接受者是 T 的方法;而类型 *T变量拥有接受者是 T 和 *T 的方法,换句话,当实现了一个接收者是值类型的方法,就可以自动生成一个接收者是对应指针类型的方法,因为两者都不会影响接收者。但是,当实现了一个接收者是指针类型的方法,如果此时自动生成一个接收者是值类型的方法,原本期望对接收者的改变(通过指针实现),现在无法实现,因为值类型会产生一个拷贝,不会真正影响调用者。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值