TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Nil in Go is typed in theory and sort of untyped in practice

127 pointsby goranmoominabout 4 years ago

8 comments

jerfabout 4 years ago
For some context, I&#x27;ve been programming in Go for about six years now, and I&#x27;ve literally never even thought about this.<p>In general, you really haven&#x27;t got much reason to be worried about something&#x27;s &quot;interface type&quot;, because if you&#x27;re really worried about something&#x27;s &quot;type&quot; (which can happen) you are almost certainly worried about it&#x27;s &quot;concrete type&quot;. The only interesting thing you can ask about the interface type directly would be &quot;Does the value inside this interface implement this interface?&quot;, and the answer is statically yes, the compiler assured that, and the interface type is statically assured at runtime, so it&#x27;s not a very interesting question. Even if fmt added a way to &quot;see&quot; the interface type passed in, I can&#x27;t imagine what it would be useful for, because it could only ever be:<p><pre><code> var x SomeInterfaceType &#x2F;&#x2F; some number of lines of code fmt.Printf(&quot;%I\n&quot;, x) </code></pre> which would statically print &quot;SomeInterfaceType&quot;.<p>So, I mean, it&#x27;s not like anything said in that blog post is <i>false</i> necessarily, but if you&#x27;re collecting reasons to hate on Go&#x27;s nil handling, there&#x27;s no real justification in adding this to your list. I&#x27;d also add that I answer newbie questions a lot on Reddit, and nothing even remotely like this has ever come up there, either.
评论 #26653168 未加载
评论 #26651001 未加载
评论 #26652154 未加载
neildabout 4 years ago
The predeclared identifier nil is a constant, like 0 or &quot;&quot;.<p>Like 0 or &quot;&quot;, nil is untyped. Go has both typed and untyped constants. 0 also is untyped, which is why you can write x==0 regardless of whether x is an int32 or an int64.<p>Unlike 0 or &quot;&quot;, nil does not have a default type. The default type of a constant is the type that it is implicitly converted to when a type is required. For example, &quot;x := 0&quot; declares a new value x with the value 0, but 0 is untyped. Untyped integer constants have a default type of int, so x is given the type int.<p>Since nil does not have a default type, it&#x27;s an error to write &quot;x := nil&quot;.<p>You can declare a typed constant with the value 0 or nil. int32(0) is a constant with type int32 and the value 0. (* int32)(nil) is a constant with the type pointer-to-int32 and the value nil.<p>Variables of an interface type can hold any value that satisfies the interface. For example, a value of type io.Reader can hold any value that has a Read method with the appropriate signature.<p>The common confusion about nil occurs because you can compare an interface value to a non-interface value.<p><pre><code> var b *bytes.Buffer &#x2F;&#x2F; b is a variable with type *bytes.Buffer var r io.Reader &#x2F;&#x2F; r is a variable with type io.Reader r = b &#x2F;&#x2F; r now holds a value with type *bytes.Buffer and value nil b == nil &#x2F;&#x2F; true: b is nil r == b &#x2F;&#x2F; true: r and b are equal r == (io.Reader)(nil) &#x2F;&#x2F; false: r is not a nil io.Reader r == (*bytes.Buffer)(nil) &#x2F;&#x2F; true: r contains a nil *bytes.Buffer r == nil &#x2F;&#x2F; false: r is not a nil io.Reader </code></pre> The confusing part is that last line. How can r not be nil, when it contains a nil value? And the reason is hopefully apparent from the previous two lines: It depends on the type of &quot;nil&quot;.<p>Whether you find this a wart in the language or not, this is not a case of nil being either typed in theory or untyped in practice. The predeclared identifier &quot;nil&quot; is an untyped constant.
评论 #26650084 未加载
评论 #26649844 未加载
评论 #26650580 未加载
评论 #26651448 未加载
评论 #26656629 未加载
评论 #26658815 未加载
评论 #26649883 未加载
评论 #26649644 未加载
kazinatorabout 4 years ago
I&#x27;m afraid this rings slightly hollow for me.<p>We can likewise claim about C that &quot;0 in C is typed in theory and sort of untyped in practice&quot; because constant expressions of integer type that evaluate to 0 can serve as null pointers of any type:<p><pre><code> char *p = 0; &#x2F;&#x2F; no cast required if (p == 0) ... &#x2F;&#x2F; no cast required time_t t = time(0); &#x2F;&#x2F; fine char *q = 1; &#x2F;&#x2F; error; requires (char *) 1. </code></pre> We can&#x27;t think of this 0 as an object; it&#x27;s just a source code token that provides a null pointer of the right type, which is statically obvious from the use.<p>The only time it&#x27;s a problem is in unsafe interfaces:<p><pre><code> int old_style_string_fun(); int variadic_fun(char *first, ...); old_style_string_fun(0); variadic_fun(&quot;first&quot;, 0); </code></pre> Here, the wrong type is inferred; the 0 just behaves like the ordinary constant of type int. A null pointer to char was intended, which requires (char *) 0 must be used.<p>None of this challenges the fact that we can have a variable of type <i>int</i>, whose value is 0.
评论 #26653997 未加载
temacabout 4 years ago
I&#x27;m not sure why it would be significantly better to have reliably &quot;typed nil&quot; over &quot;untyped nil&quot;. The concept has no real definition to begin with: what matters about sound typing are the static guarantees a type brings, or by association even if this not really the same concept, the &quot;dynamic guarantees&quot; about the behavior of objets of some &quot;dynamic type&quot; (that is the variable used as a handle to the objet had no guarenteed static type, but in most cases the object themselves <i>have</i> a type). Acting on a &quot;type&quot; of nil values seems to make very little sense. Maybe there are obscur constructs where this would be handy, but at the first glance I would consider it probably indicative of a dirty hack, and recommend looking for alternate solutions.
评论 #26649841 未加载
评论 #26664032 未加载
macintuxabout 4 years ago
Much discussion about nil in Go just yesterday:<p><a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=26635529" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=26635529</a>
migaabout 4 years ago
It is very confusing that equality in JavaScript is not transitive: <a href="https:&#x2F;&#x2F;imgur.com&#x2F;5pFXFbR" rel="nofollow">https:&#x2F;&#x2F;imgur.com&#x2F;5pFXFbR</a>.<p>Apparently equality in Go is no longer transitive either...
评论 #26653574 未加载
评论 #26650356 未加载
评论 #26655307 未加载
tapirlabout 4 years ago
&#x27;nil&#x27; in Go is just an identifier to represent the zero values of some kinds of type. A bare nil is always untyped and it is the only untyped value which has not a default type.<p>Zero values behave the same as non-zero values in many aspects.<p>More read: nils in Go <a href="https:&#x2F;&#x2F;go101.org&#x2F;article&#x2F;nil.html" rel="nofollow">https:&#x2F;&#x2F;go101.org&#x2F;article&#x2F;nil.html</a><p>The facts that several kinds of type share the same zero value literal representation really confuse many new gophers, but this is hardly a problem when you get familiar with the design.<p>There are proposals to remove the new-gopher confusion.<p>* <a href="https:&#x2F;&#x2F;github.com&#x2F;golang&#x2F;go&#x2F;issues&#x2F;22729" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;golang&#x2F;go&#x2F;issues&#x2F;22729</a> use different zero identifiers for different kinds of type<p>* I remembered that there is a propsoal which propose using `null` for non-interface zero values but still using `nil` for interfaces. I couldn&#x27;t find this issue now.
ivanechabout 4 years ago
This reminds me of Rich Hickey&#x27;s &quot;Maybe Not&quot; talk