上卷 程序设计
中卷 标准库
- bufio 1.18
- bytes 1.18
- io 1.18
- container 1.18
- encoding 1.18
- crypto 1.18
- hash 1.18
- index 1.18
- sort 1.18
- context 1.18
- database 1.18
- connection
- query
- queryrow
- exec
- prepare
- transaction
- scan & null
- context
- tcp
- udp
- http
- server
- handler
- client
- h2、tls
- url
- rpc
- exec
- signal
- embed 1.18
- plugin 1.18
- reflect 1.18
- runtime 1.18
- KeepAlived
- ReadMemStats
- SetFinalizer
- Stack
- sync 1.18
- atomic
- mutex
- rwmutex
- waitgroup
- cond
- once
- map
- pool
- copycheck
- nocopy
- unsafe 1.18
- fmt 1.18
- log 1.18
- math 1.18
- time 1.18
- timer
下卷 运行时
源码剖析
附录
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
SetFinalizer
为对象设置一个析构函数,在被 GC 回收时执行。
当 GC 发现目标对象不可达时,它先解除析构函数关联,并在一个特定 goroutine 执行该函数。为使析构函数正确执行,目标对象被重新标记为可达。等下次回收时,已没有关联析构函数,目标对象被正确回收。
- 无法确定执行时间,不能保证一定被执行。
- 无法保证零长度对象的析构函数被执行。
- 全局变量(非堆存储)不应有析构函数。
- 析构函数在单个 goroutine 运行,不应阻塞或执行太久。
- 用
KeepAlive
标记可达位置,阻止析构函数执行。 - 调用
SetFinalizer(obj, nil)
清除析构函数。
package main import ( "fmt" "runtime" "time" ) func main() { d := make([]byte, 100<<20) fmt.Printf("%p\n", &d) runtime.SetFinalizer(&d, func(o *[]byte) { fmt.Printf("%p drop!\n", o) }) for i := 0; i < 5; i++ { time.Sleep(time.Second) runtime.GC() } // runtime.KeepAlive(&d) } /* $ go build && GODEBUG=gctrace=1 ./test 0xc00009a018 0xc00009a018 drop! */
验证循环引用(cycle reference)导致无法回收,造成内存泄漏。
package main import ( "runtime" "time" ) func main() { for { func() { type data struct { x *data _ [1<<20]byte } a, b := data{}, data{} a.x = &b b.x = &a runtime.SetFinalizer(&a, func(*data) { println("a!") }) runtime.SetFinalizer(&b, func(*data) { println("b!") }) }() runtime.GC() time.Sleep(time.Millisecond * 100) } } /* $ go build && GODEBUG=gctrace=1 ./test gc 26 @2.678s 0%: ..., 102->102->104 MB, 203 MB goal, ..., 2 P (forced) gc 27 @2.788s 0%: ..., 106->106->108 MB, 211 MB goal, ..., 2 P (forced) gc 28 @2.896s 0%: ..., 110->110->112 MB, 219 MB goal, ..., 2 P (forced) gc 29 @3.005s 0%: ..., 114->114->116 MB, 228 MB goal, ..., 2 P (forced) */
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论