问题

怎么避免内存逃逸

怎么答

runtime/stubs.go:133有个函数叫noescapenoescape可以在逃逸分析中隐藏一个指针。让这个指针在逃逸分析中不会被检测为逃逸

 // noescape hides a pointer from escape analysis.  noescape is// the identity function but escape analysis doesn't think the// output depends on the input.  noescape is inlined and currently// compiles down to zero instructions.// USE CAREFULLY!//go:nosplitfunc noescape(p unsafe.Pointer) unsafe.Pointer {x := uintptr(p)return unsafe.Pointer(x ^ 0)
}

举例

  • 通过一个例子加深理解,接下来尝试下怎么通过 go build -gcflags=-m 查看逃逸的情况。
package mainimport ("unsafe"
)type A struct {S *string
}func (f *A) String() string {return *f.S
}type ATrick struct {S unsafe.Pointer
}func (f *ATrick) String() string {return *(*string)(f.S)
}func NewA(s string) A {return A{S: &s}
}func NewATrick(s string) ATrick {return ATrick{S: noescape(unsafe.Pointer(&s))}
}func noescape(p unsafe.Pointer) unsafe.Pointer {x := uintptr(p)return unsafe.Pointer(x ^ 0)
}func main() {s := "hello"f1 := NewA(s)f2 := NewATrick(s)s1 := f1.String()s2 := f2.String()_ = s1 + s2
}

执行go build -gcflags=-m main.go

$go build -gcflags=-m main.go
# command-line-arguments
./main.go:11:6: can inline (*A).String
./main.go:19:6: can inline (*ATrick).String
./main.go:23:6: can inline NewA
./main.go:31:6: can inline noescape
./main.go:27:6: can inline NewATrick
./main.go:28:29: inlining call to noescape
./main.go:36:6: can inline main
./main.go:38:14: inlining call to NewA
./main.go:39:19: inlining call to NewATrick
./main.go:39:19: inlining call to noescape
./main.go:40:17: inlining call to (*A).String
./main.go:41:17: inlining call to (*ATrick).String
/var/folders/45/qx9lfw2s2zzgvhzg3mtzkwzc0000gn/T/go-build763863171/b001/_gomod_.go:6:6: can inline init.0
./main.go:11:7: leaking param: f to result ~r0 level=2
./main.go:19:7: leaking param: f to result ~r0 level=2
./main.go:24:16: &s escapes to heap
./main.go:23:13: moved to heap: s
./main.go:27:18: NewATrick s does not escape
./main.go:28:45: NewATrick &s does not escape
./main.go:31:15: noescape p does not escape
./main.go:38:14: main &s does not escape
./main.go:39:19: main &s does not escape
./main.go:40:10: main f1 does not escape
./main.go:41:10: main f2 does not escape
./main.go:42:9: main s1 + s2 does not escape

其中主要看中间一小段

./main.go:24:16: &s escapes to heap    //这个是NewA中的,逃逸了
./main.go:23:13: moved to heap: s
./main.go:27:18: NewATrick s does not escape // NewATrick里的s的却没逃逸
./main.go:28:45: NewATrick &s does not escape

解释

  • 上段代码对AATrick同样的功能有两种实现:他们包含一个 string ,然后用 String() 方法返回这个字符串。但是从逃逸分析看ATrick 版本没有逃逸。
  • noescape() 函数的作用是遮蔽输入和输出的依赖关系。使编译器不认为 p 会通过 x 逃逸, 因为 uintptr() 产生的引用是编译器无法理解的。
  • 内置的 uintptr 类型是一个真正的指针类型,但是在编译器层面,它只是一个存储一个 指针地址int 类型。代码的最后一行返回 unsafe.Pointer 也是一个 int
  • noescape()runtime 包中使用 unsafe.Pointer 的地方被大量使用。如果作者清楚被 unsafe.Pointer 引用的数据肯定不会被逃逸,但编译器却不知道的情况下,这是很有用的。
  • 面试中秀一秀是可以的,如果在实际项目中如果使用这种unsafe包大概率会被同事打死。不建议使用! 毕竟包的名字就叫做 unsafe, 而且源码中的注释也写明了 USE CAREFULLY!

文章推荐:

  • golang面试题:简单聊聊内存逃逸?
  • golang面试题:字符串转成byte数组,会发生内存拷贝吗?
  • golang面试题:翻转含有中文、数字、英文字母的字符串
  • golang面试题:拷贝大切片一定比小切片代价大吗?
  • golang面试题:能说说uintptr和unsafe.Pointer的区别吗?

如果你想每天学习一个知识点,关注我上面的【公】【众】【号】【golang小白成长记】。

golang byte转string_golang面试题:怎么避免内存逃逸?相关推荐

  1. golang byte转string_Golang和Rust语言常见功能/库

    时下最流行.最具发展前途的的两门语言是Golang和Rust.Golang语言简洁.高效.并发.并且有个强大的囊括了常见功能标准库.与之相对比,Rust语言则主要是安全.高性能.虽然Rust没有gol ...

  2. golang byte转string_golang版memcached之groupcache缓存入门

    概述 groupcache is a distributed caching and cache-filling library, intended as a replacementfor a poo ...

  3. golang byte转string_golang系列——实战http服务器

    上一篇讲解了client端相关的知识,这一篇讲解服务端.golang语言可以快速实现一个简单的server端,如下所示: package 上述代码就轻松实现一个监听本地8000端口的服务端.大家可能注 ...

  4. golang []byte 和 string相互转换

    原文链接:golang []byte和string相互转换 测试例子 package mainimport ("fmt" )func main() {str2 := "h ...

  5. golang byte 和 java byte 的区别

    大家应该都了解,java byte 的范围是 -128-127,而golang byte 是uint8的别名,范围是0-255.那么要把java byte 转成 golang byte 怎么转呢? 方 ...

  6. Golang byte 拼接方法性能对比

    Golang byte 拼接方法性能对比 最近项目上遇到需要将[]Byte进行拼接的需求,对[]Byte拼接的各种方法进行了对比,测试代码如下: package main import (" ...

  7. golang int 转string_Golang的逃逸分析

    逃逸分析 逃逸分析(Escape Analysis)指的是将变量的内存分配在合适的地方(堆或者栈). 在函数中申请内存有2种情况: - 如果内存分配在栈(stack)上,当函数退出的时候,这部分内存会 ...

  8. Golang的GC和内存逃逸

    简介 每个版本的Golang的垃圾回收都在不断优化中,而且方法和策略都在变化,因此这里只是总结出以下几个关键点: 什么样的数据需要GC 触发GC的条件是什么 GC时发生了什么 能否从代码层面上提高GC ...

  9. C++面试题-指针-动态内存指针

    C++面试题-指针-动态内存指针 问:什么是内存泄漏和内存溢出? 答:内存泄漏:在程序申请内存后,该内存不再会被引用,但是不能释放该内存空间.如果你delete指针之后,该空间不能归还,自己又不能进行 ...

最新文章

  1. 腾讯和头条,构建类脑神经元网络的两条路线之争
  2. Hyperledger Fabric 智能合约实战 (7) windows安装fabric
  3. Unity 高清渲染管线 ShaderGraph 实现简单的表面水流效果
  4. 汇编语言(二)之数值求和
  5. PHP中获取星期的几种方法
  6. Castle动态代理拦截器可跟踪模型更改和触发规则
  7. Qt: 非阻塞时间延迟;
  8. 利用Python进行数据分析(2) 尝试处理一份JSON数据并生成条形图
  9. 恒强制版系统980_恒功率、大功率及无线充电,充电设备面临哪些趋势和挑战?...
  10. 公司小规模纳税人税务零申报操作说明
  11. (软件测试)代码覆盖(语句覆盖,分支覆盖,条件覆盖,条件组合覆盖,路径覆盖)
  12. 解决web系统session劫持
  13. 深度学习CTR模型粗略记录
  14. 12-机械键盘和普通键盘的区别
  15. 手把手教你写批处理-批处理的介绍
  16. 教你小小JAVA爬虫爬到HDU首页(只为学习)
  17. Java基础--object类详解
  18. window手动注册达梦ODBC驱动
  19. 基于SOCK_RAW的泛洪攻击
  20. 制作pDF 格式电子书

热门文章

  1. 常见的大数据安全5个问题和解决策略
  2. offset must be non-negative and no greater than buffer length (0)(tensorflow.keras)
  3. 线性回归和广义线性回归
  4. html 并集选择器,HTML+CSS基础 并集选择器
  5. python将list转为数组_python如何将list中的字符转为数字
  6. 各种门锁的内部结构图_逃生门锁,我们的生命之锁!
  7. asp sql 导出 excel_使用SQL进行数据分析(八)
  8. 应用联合服务 云计算拉近应用和操作距离
  9. 出现( linker command failed with exit code 1)错误总结
  10. careercup-链表 2.4