Does operator := always cause a new copy to be created if assign without reference?

polaris · · 411 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Imagine I have this code</p> <pre><code>type someStruct struct { listofStruct []someOtherStruct } copy1 := someStruct.listofStruct[0] copy2 := &amp;someStruct.listofStruct[0] </code></pre> <p>I would imagine <code>copy1</code> and <code>copy2</code> have the same address</p> <pre><code>fmt.Printf(&#34;%p&#34;, &amp;copy1) fmt.Printf(&#34;%p&#34;, &amp;*copy2) </code></pre> <p>But I found that they have different address, in fact <code>&amp;copy1</code> is always a different address depending on how many times you called it.</p> <p>I thought only when doing function calls does copy by value create a new copy like</p> <pre><code>callAFunction(myStruct) // This is a new copy of myStruct func callAFunction(copy myStruct ) callAFunction(&amp;myStruct) // This is a reference to the original myStruct func callAFunction(ref &amp;myStruct ) </code></pre> <p>Can someone explain to me what is the rule of <code>:=</code>? And if it does copy the struct does it do deep copy or shallow copy?</p> <hr/>**评论:**<br/><br/>drvd: <pre><p>This all is very easy once you stop using inappropriate terms while thinking of it. It is not helpful to ask about the hair color or the accent of a bacterium. These are categories applicable to humans. Same in Go: there are no references in Go and there are no &#34;shallow&#34; copies (and no &#34;deep&#34; copy, all there is are copies of values).</p> <p>Putting &amp; before a variable does not produce a reference, simply because there are no references in Go. It produces a value of totally different type:</p> <pre><code>var i int = 3 // create variable of type int and store 3 in this variable var p *int = &amp;i // create variable of type *int and store memory location of i init </code></pre> <p>Note that <code>p</code> is not a &#34;reference to i&#34;. It is not. Forget that now and forever. <code>p</code> is a pointer to an int and nothing else.</p> <p>The same applies to <code>:=</code>. This operator creates a new variable and assigns a value to it. The type is inferred for your convenience from the right hand side. So your</p> <pre><code>copy1 := someStruct.listofStruct[0] copy2 := &amp;someStruct.listofStruct[0] </code></pre> <p>is basically (writing out the type interference)</p> <pre><code>var copy1 someOtherStruct = someStruct.listofStruct[0] var copy2 *someOtherStruct = &amp;someStruct.listofStruct[0] </code></pre> <p>And now you see that <code>copy1</code> and <code>copy2</code> are totally unrelated. The have completely different types. <code>copy1</code> really is a copy of someStruct.listofStruct[0]: It has the same type and was assigned via = so a copy was made. On the other hand <code>copy2</code> is <strong>not</strong> a &#34;copy&#34;. You asked the compile the &#34;give me the memory address of someStruct.listofStruct[0] and store this value in copy2 (make this an appropriate pointer type)&#34;. Absolutely no copying here.</p> <p>Pointers are totally normal values. Making a copy of a pointer value makes a copy of a pointer value. No magic here. No deep or shallow copy, no references. Same like making a copy of an int or a complex256.</p> <p>By dereferencing a pointer you can &#34;get back to the object pointed too&#34;. This is the only &#34;reference&#34; like step. In your case you can modify what copy2 points to by <code>*copy2 = ...</code>. Note the * which dereferences copy2 (if copy2!=nil).</p> <p>What everybody irritates at first is that some Go types use pointers internally: especially Maps and Slices. E.g. a slice is a view into an underlying backing array and two slices may look at the same backing array and each slice may modify what the other sees (as the see the same backing array). Such types have reference semantics.</p></pre>rat9988: <pre><p>I just want to add something that helped me long ago and that I think is true in Go/C++/C :<br/> A variable is just an adress location. Instead of telling the computer store this serie of bits in 0x015c5c15c1c5, you tell him to store it in Variable1. Variable1 is just a nicer name of a memory adress location.</p> <p><em>Please correct me if I&#39;m worng</em></p></pre>Kraigius: <pre><p>Variables refer to some stored value but they are just symbolic names for the programmers. Yes, it&#39;s just a nicer name of a memory address location, but the computer doesn&#39;t care and will replace them when compiling. Variable1 won&#39;t exists, it&#39;s all 0x015c5c15c1c5.</p></pre>Kraigius: <pre><blockquote> <p>Note that p is not a &#34;reference to i&#34;. It is not. Forget that now and forever. p is a pointer to an int and nothing else.</p> </blockquote> <p>To be fair with OP, reference and pointer are terms often used interchangeably. The only context that I knew where a distinction matters is when we&#39;re talking about passing by reference to a function. </p> <p>After searching to understand what you meant, I only just learned that in C++ a reference means a static pointer/alias to another variable.</p></pre>drvd: <pre><blockquote> <p>reference and pointer are terms often used interchangeably</p> </blockquote> <p>And that is the root cause of the problem. Some languages <em>do</em> have actual references and they do behave differently because they <em>are</em> references.</p> <p>If you are trying to do physics and use energy and power interchangeably you will have a very hard time. These are different concepts and mixing them up just &#34;everyday usage&#34; of these terms might mean something similar will lead to major problems understanding the fundamentals.</p> <p>It is never helpful to even mention the term &#34;reference&#34; when talking about pointers in Go.</p></pre>tjholowaychuk: <pre><p>It&#39;s always a copy, even in the pointer case it&#39;s a copy, it just happens to be a copy of the pointer. Unless I&#39;m wrong :D but I believe that&#39;s correct in all cases. If you keep using &amp; you&#39;re just taking the address of that pointer, and the next pointer, and so on.</p></pre>8lall0: <pre><p>You are simply declaring different stuff. copy1 is an element that CONTAINS a copy of list[0], copy2 is a pointer to the element [0].</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

411 次点击  
加入收藏 微博
0 回复
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传