<p>I ask just out of curiosity, and trying to understand how things work internally. =)</p>
<p>Take a look on what I tried: <a href="https://play.golang.org/p/pqYju9VpA9" rel="nofollow">https://play.golang.org/p/pqYju9VpA9</a></p>
<p>It panics if you try to change the inner <code>[]byte</code> of an <code>string</code>. I'm curious about how Go knows if an <code>[]byte</code> is a <code>string</code> constant or not.</p>
<hr/>**评论:**<br/><br/>TheMerovius: <pre><p>strings and slices have a different memory layout: <a href="http://godoc.org/reflect#StringHeader" rel="nofollow">string</a> vs. <a href="http://godoc.org/reflect#SliceHeader" rel="nofollow">slice</a>. For both, the <code>Data</code> element points to the raw bytes. So, first, when you cast <code>*(*[]byte)(unsafe.Pointer(&foo))</code>, you are setting the cap-element of that new slice to… something undefined. Whatever garbage lies behind that string-header.</p>
<p>Secondly, Go decides to put the string-contents in read-only memory (because it's a compile-time constant), so trying to modify that will segfault, because you are violating the memory protection of that data. So to actually modify a string, you need to make sure that it's dynamically allocated.</p>
<p>Lastly, you need to adhere to the <a href="http://godoc.org/unsafe#Pointer" rel="nofollow">unsafe.Pointer rules</a>, if you want even a <em>smidge</em> of safety here. Otherwise the GC might switch move around data under your nose and you end up with a pointer to invalid memory.</p>
<p>So, <a href="https://play.golang.org/p/N9xKsDAwLu" rel="nofollow">this works</a>. I hope, the hoops this has to jump through, make clear how friggin' subtle usage of unsafe is. You could only ever use this, if you're <em>absolutely certain</em>, that the contents of the slice won't be modified when passing it on, or you're <em>absolutely certain</em>, that it's safe to do so. Usually, at least one of the two isn't given. And even if it is, you still need to be very aware of what you are doing.</p>
<p>So, needless to say, <em>don't do this</em>, even if you think it's a good idea. It very, very likely isn't.</p></pre>gopher1717: <pre><p>Great explanation!</p>
<blockquote>
<p>So, needless to say, don't do this, even if you think it's a good idea. It very, very likely isn't.</p>
</blockquote>
<p>Don't worry, I know it's a good idea. I was just playing with the language, and looking for knowledge.</p></pre>icholy: <pre><p>This is as far as I got: <a href="https://play.golang.org/p/qpLrREIA_r" rel="nofollow">https://play.golang.org/p/qpLrREIA_r</a></p></pre>egonelbre: <pre><p>Some strings are placed into read-only section in executable... but that can only be done to strings that exist at compile-time.</p>
<p>For example, if the string is on the heap the modification would succeed: <a href="https://play.golang.org/p/QxBIGjbjWL" rel="nofollow">https://play.golang.org/p/QxBIGjbjWL</a></p>
<p><em>This, of course, isn't guaranteed behavior.</em></p></pre>bkeroack: <pre><p>Your example is very strange.</p>
<p><a href="https://play.golang.org/p/NpFR2z8kTW" rel="nofollow">https://play.golang.org/p/NpFR2z8kTW</a></p>
<p>It works fine.</p></pre>gopher1717: <pre><p>What I was trying to do something like this:</p>
<pre><code>// code to change "foo" constant to "bar"
fmt.Println("foo") // would print "bar"
</code></pre>
<p>Because all <code>"foo"</code> in your code share the same memory address.</p>
<p>This does a copy, actually:</p>
<pre><code>bytes := []byte("foo")
</code></pre></pre>elagergren: <pre><p>If the compiler knows the string at compile time it'll put it in read-only memory, which means you can't modify it with <code>unsafe</code>. However, if you convert a slice of bytes to a string and then use <code>unsafe</code> it'll work just like you want.</p>
<p>All of the above is an implementation detail, though.</p></pre>dominikh: <pre><p>In case abusing Go one way wasn't enough, here's another: <a href="https://play.golang.org/p/uYW5UjbKYv" rel="nofollow">https://play.golang.org/p/uYW5UjbKYv</a></p></pre>gopher1717: <pre><p>This makes sense for me. Thanks for the explanation.</p></pre>elagergren: <pre><p>cheers</p></pre>twisted1919: <pre><p>Hehe, good luck trying this on utf-8 strings.</p></pre>
Is it possible to hack Go and modify the content of a string, despite it being immutable?
xuanbao · · 471 次点击这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传