Should the Go compiler catch this nil pointer dereference? If not, why?

polaris · · 536 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Was reading about <a href="https://swift.org/about/">Swift</a> and read that</p> <blockquote> <p>Another safety feature is that by default Swift objects can never be nil, and trying to make or use a nil object will results in a compile-time error.</p> </blockquote> <p>Is there a special reason why the Go compiler doesn&#39;t prevent us from doing the following?</p> <pre><code>package main import &#34;fmt&#34; func main() { type Foo struct{ Bar string } var f *Foo fmt.Println(f.Bar) } </code></pre> <p>Output:</p> <pre><code>panic: runtime error: invalid memory address or nil pointer dereference [signal 0xb code=0xffffffff addr=0x0 pc=0x20102] goroutine 1 [running]: main.main() /tmp/sandbox264712853/main.go:8 +0x102 </code></pre> <p><a href="http://play.golang.org/p/HW-b-di-Xf">http://play.golang.org/p/HW-b-di-Xf</a></p> <hr/>**评论:**<br/><br/>SteveMcQwark: <pre><p>In Go, <code>nil</code> is a valid value. Yes, dereferencing it causes a runtime error, but so does dividing by zero. Had <code>Bar</code> been a pointer method rather than a field, it could have potentially executed without any error. As a result, a heuristic to prevent dereferencing nil could never be exhaustive in Go. That means that which cases would potentially be caught and which wouldn&#39;t would become implementation dependent, since different heuristics might be used. This is generally bad, since it makes what constitutes a legal program somewhat arbitrary and hard for a user to predict, not to mention potentially non-portable. As a result, this kind of analysis is better suited to tools like go vet. Go only does this type of analysis in the most limited situations, such as dividing by a literal zero.</p> <p>Swift catches this case because <code>nil</code> isn&#39;t a valid value unless you&#39;re using an explicitly optional type, and then you have to unwrap the optional in order to access the contained value. This requires a more complex type system. It&#39;s also incompatible with Go&#39;s simpler initialization strategy, which is that every type has a zero value which it can be initialized to by default without calling any user code. Swift requires more complex initialization tracking, since there&#39;s no value that can be chosen as a default. If you use implicitly optional types in Swift, you get the same behaviour as in Go.</p></pre>forgotmypasswordduh: <pre><p>I think it should but it is more complicated of a problem than it seems. Especially if you don&#39;t want to require additional annotations. Basically, every other function may mutate your pointer at some point so it requires to follow through the program to monitor the pointer value. That would require probably whole program analysis. Or maybe via separation logic, it could be possible to compartmentalize the analysis.</p></pre>thepciet: <pre><p>Objects are devalued in Go, memory and instructions are clearly split and composed with interfaces and structs, with package APIs taking the role of organizing code, instead of big classes or class hierarchies.</p></pre>nliadm: <pre><p>The struct isn&#39;t nil, the pointer is.</p></pre>: <pre><p>[deleted]</p></pre>forgotmypasswordduh: <pre><p>Why Rust everywhere for every single thing. Option in Rust have their own sets of issues... And it is not even escape analysis. I&#39;m starting to be terrified by what I see online even from people who should know better.</p></pre>nsan1129: <pre><p>Curious to know what sorts of issues Options in Rust have. Do they fail to prevent the use of null pointers or do they create other even larger problems?</p></pre>: <pre><p>[deleted]</p></pre>forgotmypasswordduh: <pre><p>I&#39;m sorry you took my comment that way.</p> <p>At the same time, I don&#39;t see what Rust has to do with the question. And the last comment was not aimed at you but more of a general feeling of mine (which I should not have expressed perhaps). </p> <p>To keep short, escape analysis is not sufficient here. What you want is data flow analysis. You are not only looking at lifetimes but also values and how they change throughout the program. (as I explained to the OP)</p></pre>thepciet: <pre><p>Looks right to me. Why would you have a pointer and not use it? Use Unit Tests to catch these easy assertions before committing a change. Your code is incorrect.</p></pre>

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

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