Typed Nils in Go 2

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

This was an experience report on a gotcha in go, catches every go programmer at least once. The following program was extracted from a larger version, caused my co-workers to lose several hours today.

Package Mainimport "FMT" type T struct{}func (T T) F () {}type P interface {        f ()}func NewT () *t {return new (t)}type Th ing struct {        p}func factory (p p) *thing {         return &thing{p:p}}const enable_feature = Falsefunc Main () {        T : = NewT ()        t2: = t        if! enable_feature {                t2 = nil        }        thing: = Factory (T2)        FMT. Println (thing. P = = nil)}

This distilled version of the program in question, while non-sensical, contains all the attributes of the original. Take some time to study the program and ask yourself, does the program print true or false ?

Nil! = Nil

Not to spoil the surprise and the program prints false . The reason is, while was nil assigned to t2 , when was t2 passed to factory it was "boxed" into an variable of type ; An interface. Thus, thing.P does not equal nil because P nil while the value of is, its concrete type is *T .

Typednil

You ' ve probably realised the cause of this problem are the dreaded typed nil, a gotcha that have its own entry in T He Go FAQ. The typed nil emerges as a result of the definition of a interface type; A structure which contains the concrete type of the value stored in the interface, and the value itself. This structure can ' t is expressed in pure Go, but can is visualised with this example:

var n int = var i interface{} = n

The interface value i is assigned a copy n of the value of in, so i ' s type slot holds n ' s type; , and it ' s data slot holds the value 200 . We can write this to more concisely as (int, 200) .

The original program we effectively has the following:

var t2 *t = Nilvar p p = t2

Which results in p , using our nomenclature, holding the value (*T, nil) . Why does the expression p == nil evaluate to false ? The explanation I prefer is:

  • nilis a compile time constant which was converted to whatever type was required, just as constant literals like be 200 conve RTed to the required integer type automatically.
  • Given the expression p == nil , both arguments must be of the same type, therefore are converted to the nil same Type p as, which is an interface type. So we can rewrite the expression as (*T, nil) == (nil, nil) .
  • As equality in Go almost always operates as a bitwise comparison It's clear that the memory bits which hold the Inter Face value is different to the (*T, nil) bits , (nil, nil) Thus the expression evaluates tofalse.

Put simply, an interface value was only equal to nil if both the type and the value stored inside the interface is both nil .

For a detailed explanation of the mechanics behind Go ' s interface implementation, Russ Cox have a great post on his blog.

The future of typed nil s in Go 2

Typed Nils is an entirely logical result of the the-the-a-types, AKA interfaces, is implemented, but is almost NE ver what the programmer wanted. To tie the back to Russ ' s Gophercon keynote, I believe typed Nils is an example where Go fails to scale for programming Teams.

This explanation have consumed words–and several hours over chats today–to explain, and in the end my co-workers were le FT with a bad taste in their mouthes. The clarity of interfaces was soured to a suspicion that gotchas like this were lurking in their codebase. As an experienced Go programmer I ' ve learnt to being wary of the possibility of a typed nil during code review, but it is UNF Ortunate that they remain something, each Go programmer have to learn the hard.

For Go 2.0 I-D like-to-start the discussion of what it would mean if comparing a interface value to nil considered the Value portion of the interface such, the following evaluated to true :

var b *bytes. Buffervar r io. Reader = bfmt. Println (r = = nil)

There is obviously some subtleties that the pithy demand fails to capture, but a desire to make this seemingly straight Forward comparison less error prone would, at least in my mind, make Go 2 easier to scale to larger development teams.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.