上例中te的类型是func(*int),属于引用类型,参数*int也是引用类型,则调用te(j)形成了为te的参数(成员)*int赋值的现象,即te.i = j会导致逃逸 。代码中其他几种调用都没有形成 多级间接赋值 情况 。
同理 , 如果函数的参数类型是slice,map或interface{}都会导致参数逃逸 。
匿名函数的调用也是一样的 , 它本质上也是一个函数变量 。有兴趣的可以自己测试一下 。
只要使用了Interface类型(不是interafce{}) , 那么赋值给它的变量一定会逃逸 。因为interfaceVariable.Method()先是间接的定位到它的实际值,再调用实际值的同名方法,执行时实际值作为参数传递给方法 。相当于interfaceVariable.Method.this = realValue
向 channel 中发送数据,本质上就是为 channel 内部的成员赋值,就像给一个 slice 中的某一项赋值一样 。所以chan *Type,chan map[Type]Type,chan []Type,chan interface{}类型都会导致发送到 channel 中的数据逃逸 。
这本来也是情理之中的,发送给 channel 的数据是要与其他函数分享的,为了保证发送过去的指针依然可用,只能使用堆分配 。
可变参数如func(arg ...string)实际与func(arg []string)是一样的 , 会增加一层访问路径 。这也是fmt.Sprintf总是会使参数逃逸的原因 。
例子非常多,这里不能一一列举,我们只需要记住分析方法就好,即,2 级或更多级的访问赋值会容易导致数据逃逸 。这里加上容易二字是因为随着语言的发展 , 相信这些问题会被慢慢解决,但现阶段,这个可以作为我们分析逃逸现象的依据 。
下面代码中包含 2 种很常规的写法 , 但他们却有着很大的性能差距,建议自己想下为什么 。
Benchmark 和 pprof 给出的结果:
熟悉堆栈概念可以让我们更容易看透 Go 程序的性能问题,并进行优化 。
多级间接赋值会导致 Go 编译器出现不必要的逃逸,在一些情况下可能我们只需要修改一下数据结构就会使性能有大幅提升 。这也是很多人不推荐在 Go 中使用指针的原因,因为它会增加一级访问路径,而map,slice,interface{}等类型是不可避免要用到的 , 为了减少不必要的逃逸,只能拿指针开刀了 。
大多数情况下,性能优化都会为程序带来一定的复杂度 。建议实际项目中还是怎么方便怎么写,功能完成后通过性能分析找到瓶颈所在,再对局部进行优化 。
golang 方法返回的结构体为什么取不到地址?golang方法(method)返回值提取结构体(struct)取不到地址的原因是,①返回值并没有保存到变量中,返回值本身只是临时保存在程序运行的堆栈的某个不确定位置,不能取地址;②实参取地址用的操作符是是,而形参声明变量类型为指针,需要地址值用的才是*;③声明形参为指针的参数的实参只能为地址值 。
故先把修改后的代码列出,修改要点是把“*NewPerson1().Speak()”改为“var b=NewPerson1();(b).Speak()”,同时把“NewPerson2().Speak()”改成“var a=NewPerson2();(a).Speak()”,代码列出如下:
package main;
import "fmt";
type PersonA struct{
name string
}
func (p *PersonA) Speak () {
fmt.Println ( "person speak" ,p.name)
}
func (p PersonA) Walk ( ){
fmt . Println ( "person walk",p.name)}
func NewPerson1()(p PersonA){
【go语言method详解 go语言chan】 return PersonA{"new Person1"}}
func NewPerson2()(p PersonA){
return PersonA{"new Person2"}}
func main () {
var a=NewPerson2 (); (a).Speak ();
a .Walk ();
fmt. Println ("--------------------") ;
var b=NewPerson1 ();(b).Speak ();
b.Walk ()}
go代码调试效果
推荐阅读
- 小伙向美女要微信视频号,要美女微信的经典语录
- 小米路由器网络频闪怎么办,小米路由器网络一直闪
- 虚拟主机ip,虚拟主机ip地址怎么查
- 怎么制作正版win10u盘,如何制作win10系统盘u盘
- mysql怎么建存储过程 mysql创建存储过程sql语句
- 搞笑自媒体用什么拍摄,自媒体搞笑视频素材
- 怎么恢复u盘文件,如何恢复u盘中删除的文件
- java统计报表代码 java统计报表数据量大怎么做
- oracle取数据的最新事件,oracle 取最新的数据