Why aren't all expressions addressable?

agolangf · · 1771 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>From <a href="https://golang.org/ref/spec#Address_operators:">https://golang.org/ref/spec#Address_operators:</a></p> <blockquote> <p>For an operand x of type T, the address operation &amp;x generates a pointer of type *T to x. The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, x may also be a (possibly parenthesized) composite literal</p> </blockquote> <p>Why aren&#39;t all expressions addressable? Can&#39;t the compiler do what a human does when an unaddressable expression is referenced and insert a temporary variable to make it addressable?</p> <p>For example:</p> <p>var a = &amp;123 -&gt; var _tmp = 123; var a = &amp;_tmp</p> <hr/>**评论:**<br/><br/>TheMerovius: <pre><blockquote> <p>Why aren&#39;t all expressions addressable? Can&#39;t the compiler do what a human does when an unaddressable expression is referenced and insert a temporary variable to make it addressable?</p> </blockquote> <p>That would lead to super surprising behavior. e.g.</p> <pre><code>m := make(map[int]int) m[42] = 23 p := &amp;m[42] *p = 1337 fmt.Println(m[42], *p) // 23, 1337 fmt.Println(p == &amp;m[42]) // false </code></pre> <p>Why would this behave this way?</p></pre>indil7: <pre><p>Your example makes sense to me, though. Consider how &amp;myLRUCache.Get(123) and &amp;&lt;-myChan are similar to map elements, and why it also doesn’t make sense to use an address within the data structure in those cases. Should the special casing of slices, arrays, and structs really preclude doing something useful in the general case? We could still achieve the same thing for those types with &amp;(mySlice[123]).</p></pre>TheMerovius: <pre><blockquote> <p>Your example makes sense to me, though.</p> </blockquote> <p>I don&#39;t understand how. Or at least how you can disagree that someone learning the language would find it majorly screwed up. <code>&amp;</code> is the address-of operator. You&#39;re telling me it&#39;s fine that <code>&amp;</code> doesn&#39;t actually take the address of what you apply it to? That you take an address of a thing and then, when you modify what&#39;s pointed at, that thing doesn&#39;t actually change? Or that it&#39;s fine that <code>&amp;expr</code> might allocate new memory on every usage? And that <code>&amp;expr == &amp;expr</code> returns false?</p> <p>None of this makes any sense. That&#39;s just not how pointers are supposed to work.</p> <blockquote> <p>Consider how &amp;myLRUCache.Get(123) and &amp;&lt;-myChan are similar to map elements, and why it also doesn’t make sense to use an address within the data structure in those cases.</p> </blockquote> <p>Yes, but that&#39;s exactly <em>why</em> these things are not addressable. They are not addressable, because you can&#39;t actually safely get a pointer into them. The term &#34;addressable&#34; isn&#39;t just a random, made-up term. It means &#34;something you can get the address of&#34;.</p> <blockquote> <p>Should the special casing of slices, arrays, and structs really preclude doing something useful in the general case?</p> </blockquote> <p>What you are suggesting is to overload <code>&amp;expr</code> to <em>sometimes</em> mean &#34;take the address of expr&#34; and <em>sometimes</em> mean &#34;allocate a new value and initialize it to expr&#34;. They are very different operations, why would you use the same operator for them¹?</p> <p>Note, that it&#39;s not really about enabling things you can&#39;t already do. There is no code this would enable you to write that you can&#39;t already get with a simple <code>tmp := expr; x = &amp;tmp</code>. So I don&#39;t quite buy the &#34;doing something useful in the general case&#34; argument. You are introducing a lot of confusing situations to get a tiny bit of convenience.</p> <hr/> <p>BTW, all of this is only concerned with one occasion where addressability is used. There are more. Another implication of &#34;making every expression addressable&#34;, is that this code would reasonably have to type-check:</p> <pre><code>var b bytes.Buffer fmt.Fprintln(b, &#34;Hello world&#34;) io.Copy(os.Stdout, b) // Doesn&#39;t write anything </code></pre> <p>Another way to look at this, is that it makes pointers pretty much obsolete altogether. In a way, Go would behave like python - some things are references, some things are values, but there is no real lexical or programmatic distinction between the two. I don&#39;t like that; Go is supposed to give you control over memory layout.</p> <hr/> <p>[1] You could make the argument that we&#39;re already doing that by special-casing <code>&amp;</code> for struct-literals. Which is fair - in fact, I&#39;d argue that it was probably a mistake to do that special casing. Though it works fine in practice. Doesn&#39;t mean it&#39;s a mistake we have to replicate to more cases.</p></pre>TheMerovius: <pre><p>I should add that, if you&#39;re proposal would be &#34;make any literal addressable&#34; (i.e. extend the special-casing of struct-literals to more value literals), I&#39;d be less opposed. It&#39;s also something that has been proposed before. I&#39;m pretty sure that it&#39;s on the Go team&#39;s radar to simplify things when you want that, though they might not do it <em>exactly</em> like you are proposing.</p></pre>muddiedwaters45: <pre><p>I&#39;d rather have a two-arg overload of new(); e.g:</p> <pre><code>a := new(int, 123) </code></pre> <p>to make these cases more ergonomic.</p></pre>indil7: <pre><p>I’m not sure what you mean. Why is that more ergonomic?</p> <p>What if the expression spans multiple lines?</p></pre>

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

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