<pre><code>package main
import (
"fmt"
)
type Anything struct {
Foo string
Bar string
}
type Res struct{
Data interface{}
Error error
}
type ResChan chan Res
func fn1() ResChan {
r := make(ResChan, 1)
go func(){
res := Res{}
a := Anything{
Foo: "foobar",
Bar: "barfoo",
}
res.Data = a
r <- res
close(r)
return
}()
return r
}
func fn2() ResChan {
r := make(ResChan, 1)
go func(){
res := Res{}
a := &Anything{
Foo: "foobar",
Bar: "barfoo",
}
res.Data = a
r <- res
close(r)
return
}()
return r
}
func main() {
resFn1 := <- fn1()
aFn1 := resFn1.Data.(Anything)
fmt.Printf("%v\n", aFn1)
resFn2 := <- fn2()
aFn2 := resFn2.Data.(*Anything)
fmt.Printf("%v\n", aFn2)
}
</code></pre>
<p><a href="https://play.golang.org/p/TNWMjKLbCh" rel="nofollow">https://play.golang.org/p/TNWMjKLbCh</a> </p>
<p>Can the gc free <code>fn2</code> allocated memory?<br/>
Where does <code>a</code> life in the memory?<br/>
I'm guessing because in <code>fn2</code> the pointer gets assigned to res.Data it lifes inside the goroutines scope so the goroutine can't be freed by the gc?<br/>
Is this even an issue I have to worry about?<br/>
What would be your prefered way of doing this?<br/>
Can someone enlighten me what's actually happening in the memory here? </p>
<hr/>**评论:**<br/><br/>Sythe2o0: <pre><blockquote>
<p>Is this even an issue I have to worry about?</p>
</blockquote>
<p>If you are worried about accessing freed memory, no, that won't happen. For efficiency, instead of planning around elements of the compiler (that could change in later releases) I would benchmark it.</p></pre>ChristophBerger: <pre><p>The Go compiler does an escape analysis of all the objects that get created. If it finds that an object created inside a local scope is used outside this scope, this object automatically gets created on the heap rather than on the stack. (Hence it „escapes“ the local scope.)</p>
<p>When I run your code with escape analyis enabled and inlining disabled, I get this output:</p>
<pre><code>$ go run -gcflags '-m -l' main.go
# command-line-arguments
./main.go:22:5: func literal escapes to heap
./main.go:22:5: func literal escapes to heap
./main.go:20:11: make(ResChan, 1) escapes to heap
./main.go:30:12: a escapes to heap
./main.go:43:5: func literal escapes to heap
./main.go:43:5: func literal escapes to heap
./main.go:41:11: make(ResChan, 1) escapes to heap
./main.go:51:12: a escapes to heap
./main.go:48:9: &Anything literal escapes to heap
./main.go:64:13: aFn1 escapes to heap
./main.go:68:13: aFn2 escapes to heap
./main.go:64:12: main ... argument does not escape
./main.go:68:12: main ... argument does not escape
{foobar barfoo}
&{foobar barfoo}
</code></pre>
<p>Anything that escapes to heap is not bound to a local scope anymore, and the GC can deal with it like with any object on the heap. For <code>a</code>, this is definitely the case.</p></pre>cirowrc: <pre><p>oh, I didn't know about those flags! Thanks a bunch!</p></pre>nsd433: <pre><p>Some of the wording you're using is unclear. So I'll make some assumptions in order to answer.</p>
<p>Inside fn2() two allocates happen, one of a channel, and one of a closure which holds the channel. The closure is passed to the child goroutine. The closure can be gc'ed once both fn2 and the child goroutine of fn2 return, and the channel can be gc'ed once the closure is gc-able and main completes the '<- fn2()' operation.</p>
<p>'a' is a local variable of the goroutine of fn2. 'a' is a pointer to a struct which itself was allocated on the heap (the struct escapes via the channel). 'a' lives on the stack (and probably just in a register since it only needs to live for 2 statements). The res.Data interface{} contains a copy of 'a' in its value field.</p>
<p>I'm not sure what you mean by a goroutine being freed by gc. But in general goroutines are linked to by the scheduler, which is a global object, and thus a goroutine will not be gc'ed until it terminates. I'm not sure if that's what you're asking.</p>
<p>I don't know what worries you, but there's nothing obviously wrong with the code you have here. It's not going to crash or do strange things.</p></pre>
GC efficiency: Is sending pointers through channels via intermediat interfaces bad?
blov · · 445 次点击这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
0 回复
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传