<p>lets say i have
type Hello struct {
var1 time.Time
var2 *time.Time
}</p>
<p>when should i put struct element as another struct (var1). and when should i put struct elemnt as pointer (var2)? what tradeoff will i expect between these two? if i define var hello = &Hello{}, accessing hello.var1 is not going to give copy of var1, is it?</p>
<p>i read golang std lib in how it uses struct. sometimes it use pointer of struct as element. and sometimes struct itself. </p>
<hr/>**评论:**<br/><br/>sin2pifx: <pre><blockquote>
<p>accessing hello.var1 is not going to give copy of var1, is it?</p>
</blockquote>
<p>Does this answer your question? <a href="https://play.golang.org/p/Vb_L9Q830k" rel="nofollow">https://play.golang.org/p/Vb_L9Q830k</a></p></pre>boes13: <pre><p>thank you. so hello.var1 will give you a new copy each time accessing the variable, is it correct? i have modified yours to show this behavior <a href="https://play.golang.org/p/owXcQ-i82G" rel="nofollow">https://play.golang.org/p/owXcQ-i82G</a></p>
<p>so, isn't it better to use pointer of struct as element of other struct?</p></pre>sin2pifx: <pre><p>Not precisely, but if you assign hello.var1 to another variable, then it will copy, just like it would copy an integer. However, if you write <code>hello.var1.a += 1</code> then var1 won't be copied.</p>
<blockquote>
<p>so, isn't it better to use pointer of struct as element of other struct?</p>
</blockquote>
<p>That depends on what you want to achieve. If you need to share a member of your struct, you can use a pointer. But a pointer adds a little bit of extra runtime and memory too, so if you don't need to share (i.e. you have a unique var2 per Hello object) or you are concerned about CPU/memory usage, then embedding the struct directly makes more sense.</p>
<p>But even that is not completely accurate (it also depends on the way in which you access the embedded object and how frequently you do it), so try to understand the basic use of both and keep it simple.</p></pre>boes13: <pre><p>pointer adds extra runtime? can you explain a bit? is it related to runtime stack?</p></pre>sin2pifx: <pre><p>First: Don't worry too much about runtime when you don't really, really need it. Improving performance is a difficult task and optimizing too early can lead to problems later. I also have to add that what I'm going to describe is how the C compiler works, and I've never checked how go actually implements it.</p>
<p>Why can pointers add runtime? When you use <code>type MyStruct struct { a AnotherStruct; b int; }</code>, the compiler can put <code>a</code> and <code>b</code> in memory right next to each other. Say you have a variable <code>var x MyStruct</code>. Then <code>x.a.field</code> has the same way of access as <code>x.b</code>, since the compiler knows where both are located in memory.</p>
<p>If instead you have <code>type MyStruct struct { a *AnotherStruct; b int; }</code>, then the expression <code>x.a.field</code> first has to determine where <code>x.a</code> is pointing to. So there's an extra indirection there, and that costs an instruction or two.</p>
<p>This affects runtime if you access <code>x.a.field</code> often. If you don't access it very often, it might even need less CPU to use a pointer for <code>a</code> because of caching. It's hard to predict which solution is best, and it's not wise to optimize early, so write your code as simple as you can.</p></pre>: <pre><p>[deleted]</p></pre>boes13: <pre><p>supposed i dont need to modify the data inside struct, only accessing the elements. but still, isnt it better to define
type Foo struct {
Mybar *Bar
}
instead of
type Foo struct {
Mybar Bar
}</p>
<p>from <a href="https://play.golang.org/p/owXcQ-i82G" rel="nofollow">https://play.golang.org/p/owXcQ-i82G</a>, i tested behavior each time accessing Foo.Mybar it gave a new copy where Mybar is struct, not a pointer.</p>
<p>sorry for no formatting. i'm using phone, no available computer right now</p></pre>hobbified: <pre><blockquote>
<p>but still, isnt it better to define type Foo struct { Mybar *Bar } instead of type Foo struct { Mybar Bar }</p>
</blockquote>
<p>What is "better"?</p></pre>TheMerovius: <pre><p>There are multiple considerations. Let me call <code>S</code> the struct type and <code>F</code> the type of the field :)</p>
<ul>
<li>How do I want the thing to behave, when I copy? If I want <code>S</code> to be used as a pure value with copies, do I want <code>F</code> to be copied or not? Sharing something like a global cache might make sense, sharing something like a byte-buffer doesn't. Of course, if I want <code>S</code> to be used via a pointer anyway, then there won't be copies, usually.</li>
<li>This is probably the most important one: Does <code>F</code> have a useful zero-value? One of the rules for idiomatic go is, that you should try to have useful zero-values. For that, all your fields need a useful zero-value. <code>*F</code> will very rarely have a useful zero-value; usually you have to initialize a pointer to something useful first. <code>F</code> on the other hand might have a useful zero-value.</li>
<li>Do I care about the size of <code>S</code> and it's memory access pattern (hint: Most of the time you don't)? Using <code>*F</code> keeps <code>S</code> small, which is good if it's copied and if I expect there to be a lot of slices of <code>S</code>; cache-locality will be better. On the other hand, it will incur an additional indirection whenever the field is accessed, making cache-locality worse, so this only really helps, if the field is rarely used.</li>
</ul></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传