<p>During a peer review, I saw some code that looked like the following example:</p>
<pre><code>stringVar := "this is a string"
myStruct := MyStruct{
Attribute: &stringVar,
}
doStuff(myStruct)
stringVar = "this is another string"
doStuff(myStruct)
</code></pre>
<p><a href="https://play.golang.org/p/a-Da1QQTnM" rel="nofollow">https://play.golang.org/p/a-Da1QQTnM</a></p>
<p>I didn't think this code would behave the way that it did. I would think that since <code>stringVal</code> is a value, not a pointer, the assignment operator would create a new memory location, store the string in there and then set <code>stringVar</code> would be reset with that address. But it seems to simply store the new string in the same memory location that is already allocated for stringVar and thus changes the value that the struct points to.</p>
<p>Isn't this inconsistent with how other languages handle assignments or am I just crazy? </p>
<hr/>**评论:**<br/><br/>tcrypt: <pre><p>You're setting <code>Attribute</code> to be a pointer to a string. When you say <code>stringVar = "this is another string"</code> you're changing the string that's stored in that location to a new value. But the pointer stays the same so when you dereference the pointer you get the new string.</p>
<p><a href="http://play.golang.org/p/EdZjrzWsAQ" rel="nofollow">Here is an example that prints both the pointer and the string being pointed to.</a> You can see that the memory address stays the same but the value changes.</p></pre>izuriel: <pre><p>I'm honestly surprised this has yet to be mentioned. At the beginning the <code>:=</code> is used which allocates memory and assigns a value to that memory location. The a <em>pointer</em> to this location is passed to the struct. A method is called. Then you have a simple assignment which <em>does not</em> allocate memory (necessarily) but instead reassigns the value of the variable. The pointer to this variable is still valid, just points to a different value. It looks like <a href="http://ideone.com/aJE6wn" rel="nofollow">C++</a> behaves the same way. I would hazard most if not all languages that feature pointers behave the same way. </p>
<p>Seems that <a href="http://ideone.com/ZvVsA6" rel="nofollow">C</a> also does this.</p>
<p>Rust does not even allow it due to it's safefty guarantee with borrowed values (pointers, essentially). Although I'm sure using Arc or Rc or Box there is probably a way to do it.</p>
<p><strong>edit:</strong> added C, note about Rust</p></pre>whizack: <pre><p>The Attribute field points to the memory used by stringVar, so changing stringVar changes the value of Attribute when dereferenced because Attribute simply points at stringVar 's memory location</p></pre>lespritd: <pre><p>Go does not have immutable strings ala Java. Everything (except for consts) is a regular var.</p></pre>earthboundkid: <pre><p>That's not true. Go's strings are immutable. But he doesn't have a string in <code>MyStruct</code>, he has a <strong>pointer</strong> to a string. (Java doesn't have pointers, so there's no analog to a string pointer in Java.)</p>
<p>In any event, use of string pointers is almost always a mistaken design. The only time they are acceptable is when you're Marshalling/Unmarshalling and you need to be able to represent <code>nil</code>/<code>null</code> as distinct from <code>""</code>. Even there, <code>NullString</code> is probably a better choice.</p></pre>jrwren: <pre><p>This. Different between a value and a pointer to a value is important.</p>
<p>(Java doesn't have pointers, but all the types other than primitives are reference types. The string reference type in java is immutable.)</p></pre>earthboundkid: <pre><p>The reason strings are immutable in Java and many other languages, as far as I've ever heard, is to give hash maps something immutable to key off of. Here's an example that shows why the mutable contents of string pointers don't affect Go's map: <a href="http://play.golang.org/p/L5yIco0uMo" rel="nofollow">http://play.golang.org/p/L5yIco0uMo</a></p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传