文档章节

Golang的值类型receiver和指针类型receiver

miros
 miros
发布于 2015/04/23 14:41
字数 650
阅读 88
收藏 0

Golang的值类型和指针类型receiver一直让我比较混淆,在此做几个试验备忘

先看指针类型的receiver:

package main
import (
"fmt"
)
type BasicEvent struct {
EventId int
}
func (ev *BasicEvent) updateEventID(id int) {
ev.EventId = id
}
func main() {
ev1 := &BasicEvent{EventId: 1}
fmt.Printf("before update id = %d\n", ev1.EventId)
ev1.updateEventID(2)
fmt.Printf("After update id = %d\n", ev1.EventId)
ev2 := BasicEvent{EventId: 1}
fmt.Printf("before update id = %d\n", ev2.EventId)
ev2.updateEventID(2)
fmt.Printf("After update id = %d\n", ev2.EventId)
}

输出的结果是:

before update id = 1

After update id = 2

before update id = 1

After update id = 2

由此可见,不管调用的时候是个值还是指针,只要是方法的receiver是指针类型,都能够修改调用者的内部状态。我估计这个时候是Go自动做了指针转换。


再看值类型的receiver:

package main
import (
"fmt"
)
type BasicEvent struct {
EventId int
}
func (ev BasicEvent) updateEventID(id int) {
ev.EventId = id
}
func main() {
ev1 := &BasicEvent{EventId: 1}
fmt.Printf("before update id = %d\n", ev1.EventId)
ev1.updateEventID(2)
fmt.Printf("After update id = %d\n", ev1.EventId)
ev2 := BasicEvent{EventId: 1}
fmt.Printf("before update id = %d\n", ev2.EventId)
ev2.updateEventID(2)
fmt.Printf("After update id = %d\n", ev2.EventId)
}

输出的结果是:

before update id = 1

After update id = 1

before update id = 1

After update id = 1

由此可见,不管调用的时候是个值还是指针,只要是方法的receiver是值类型,都无法改变调用者的内部状态。


总是可见,主要关注的点是方法定义的时候到底receiver是指针还是值类型,如果receiver是指针,内部状态才可以改。


另外,关于关于传入参数是否可改的问题

package main
import (
"fmt"
)
type BasicEvent struct {
EventId int
}
func updateEventIDByPointer(ev *BasicEvent, newID int) {
ev.EventId = newID
}
func updateEventIDByValue(ev BasicEvent, newID int) {
ev.EventId = newID
}
func main() {
ev1 := &BasicEvent{EventId: 1}
fmt.Printf("before update id = %d\n", ev1.EventId)
updateEventIDByPointer(ev1, 2)
fmt.Printf("After update id = %d\n", ev1.EventId)
ev2 := BasicEvent{EventId: 1}
fmt.Printf("before update id = %d\n", ev2.EventId)
updateEventIDByValue(ev2, 2)
fmt.Printf("After update id = %d\n", ev2.EventId)
ev3 := &BasicEvent{EventId: 1}
fmt.Printf("before update id = %d\n", ev3.EventId)
updateEventIDByValue(*ev3, 2)
fmt.Printf("After update id = %d\n", ev3.EventId)
ev4 := BasicEvent{EventId: 1}
fmt.Printf("before update id = %d\n", ev4.EventId)
updateEventIDByPointer(&ev4, 2)
fmt.Printf("After update id = %d\n", ev4.EventId)
}

结果如下:

before update id = 1

After update id = 2

before update id = 1

After update id = 1

before update id = 1

After update id = 1

before update id = 1

After update id = 2

前两个比较好理解。第三个值得注意的是,对指针解引用会创建另一个值对象,所以无法改变内部状态。第四个也好说,取地址后得到了原始值对象的引用,所以可以修改内部状态。


关于如何在值类型和指针类型的receiver之间做选择,可以参考

https://github.com/golang/go/wiki/CodeReviewComments#receiver-type

© 著作权归作者所有

共有 人打赏支持
miros
粉丝 0
博文 4
码字总数 4259
作品 0
成都
私信 提问
golang sort 包使用,及三个简单排序算法冒泡,插入,选择 练习

sort 包的核心类型是 sort.Interface: type Interface interface { // Len is the number of elements in the collection. Len() int // Less reports whether the element with // index i......

yujian0231
2015/01/22
0
0
golang中method的传值与传地址

golang中,struct的method的形式如下: func (r ReceiverType) funcName(parameters) (results) 如果想要修改struct的成员的值,method被定义时候其ReceiverType必须是struct形式。如果Recei...

alexstocks
2015/01/23
0
1
Go基础编程:面向对象—方法

1 概述 在面向对象编程中,一个对象其实也就是一个简单的值或者一个变量,在这个对象中会包含一些函数,这种带有接收者的函数,我们称为方法(method)。 本质上,一个方法则是一个和特殊类型关...

tennysonsky
2017/12/28
0
0
Golang:方法

什么是方法 一个方法只是一个函数,它有一个特殊的接收者(receiver)类型,该接收者放在 关键字和函数名之间。接收者可以是结构体类型或非结构体类型。可以在方法内部访问接收者。 可以通过...

与蟒唯舞
01/05
0
0
Golang之面向对象

一、method 带有接收者的函数,称之为method。 假设定义了一个struct叫长方形,现在要计算它的面积,那么按照面向过程的思路会如下实现: packeage main import "fmt" type Rectange struct ...

xumaojun
01/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

java框架学习日志-7(静态代理和JDK代理)

静态代理 我们平时去餐厅吃饭,不是直接告诉厨师做什么菜的,而是先告诉服务员点什么菜,然后由服务员传到给厨师,相当于服务员是厨师的代理,我们通过代理让厨师炒菜,这就是代理模式。代理...

白话
今天
10
0
Flink Window

1.Flink窗口 Window Assigner分配器。 窗口可以是时间驱动的(Time Window,例如:每30秒钟),也可以是数据驱动的(Count Window,例如:每一百个元素)。 一种经典的窗口分类可以分成: 翻...

满小茂
今天
5
0
my.ini

1

architect刘源源
今天
7
0
docker dns

There is a opensource application that solves this issue, it's called DNS Proxy Server It's a DNS server that solves containers hostnames, if could not found a hostname that mat......

kut
今天
8
0
寻找数学的广度——《这才是数学》读书笔记2700字

寻找数学的广度——《这才是数学》读书笔记2700字: 文|程哲。数学学习方式之广:国内外数学教育方面的专家,进行了很多种不同的数学学习方式尝试,如数学绘本、数学游戏、数学实验、数学步道...

原创小博客
今天
14
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部