Why nil?

blov · · 978 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>So I was just bitten by this (<a href="http://play.golang.org/p/pdIQABIM75">playground</a>):</p> <pre><code>var got []float64 want := []float64{} if !reflect.DeepEqual(got, want) { fmt.Printf(&#34;got:(%T,%v) want:(%T,%v)\n&#34;, got, got, want, want) } // got:([]float64,[]) want:([]float64,[]) </code></pre> <p>This fails, even though apparently they are equal! The documentation in <code>reflect.DeepEqual</code> is thankfully very explicit:</p> <blockquote> <p>An empty slice is not equal to a nil slice.</p> </blockquote> <p>Of course, this begs the question to <em>why</em>. The case where nil doesn&#39;t equate a nil interface (<a href="https://golang.org/doc/faq#nil_error">https://golang.org/doc/faq#nil_error</a>) also stands out, specially for newcomers - in C and Java, a <code>null</code> is always a <code>null</code>. I know the technical explanation regarding how interface pointers are represented, but it just says &#34;it works as coded&#34;. Is there any other reason why nil can&#39;t be a bit more useful?</p> <hr/>**评论:**<br/><br/>dsymonds: <pre><p>They are not equal. One is a nil slice, and one is an allocated but zero length slice. Those are different things. They do, however, work equivalently in many situations, like with len, cap, append, copy, etc.</p> <p>You might find <a href="http://research.swtch.com/godata">http://research.swtch.com/godata</a> informative.</p></pre>iku_19: <pre><p>So, in theory this should be equal</p> <pre><code>var got []float64 got = make([]float64, 0, 0) want := []float64{} if !reflect.DeepEqual(got, want) { fmt.Printf(&#34;got:(%T,%v) want:(%T,%v)\n&#34;, got, got, want, want) } </code></pre></pre>dsymonds: <pre><p>Yes. The playground says those are equal.</p></pre>hobbified: <pre><ol> <li><p>A slice with nothing in it is obviously different from no slice at all. You might find it annoying that a <code>[]float64</code> is allowed to be &#34;no slice at all&#34; rather than merely empty, but preventing you from ever seeing an uninitialized slice (as dynamic languages would do) would be expensive and counter to the general design of Go.</p></li> <li><p>Nil interfaces are a bit weirder, and honestly I find it easy to read the spec in a way that says that types are irrelevant when comparing an interface value with nil. Maybe someone should rephrase it a little bit. I&#39;m pretty sure it was done the way it is for simplicity/efficiency of implementation, rather than user-friendliness.</p></li> </ol></pre>dilap: <pre><p>They are not equal in a literal sense, in that the memory used by each is different.</p> <p>That said, I think they behave exactly the same (trying to think of somewhere they don&#39;t; can&#39;t), so I&#39;m not sure exactly what purpose is served by not considering them &#39;equal&#39; for DeepEqual purposes, other than philosophical purity.</p> <p>(In contrast, a nil map doesn&#39;t act at all like an empty map, tho I wonder why [perf?].)</p></pre>brunokim: <pre><p>Yes, from what I understand now I believe == should return false, and reflect.DeepEqual should return true. After all, DeepEqual cares about semantics, not memory equality.</p></pre>

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

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