From 1e0f97ac6544ab3b7cf76e9c9d62e8c2a60bcdb6 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Fri, 17 Feb 2012 16:27:17 +1100 Subject: [PATCH] faq: add entry about nil interfaces vs. nil pointers Fixes #2778. R=bradfitz, rsc, iant, adg CC=golang-dev https://golang.org/cl/5672078 --- doc/go_faq.html | 79 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/doc/go_faq.html b/doc/go_faq.html index 93e1ea4ee51..36e1e53e58f 100644 --- a/doc/go_faq.html +++ b/doc/go_faq.html @@ -680,6 +680,85 @@ for i, v := range t { } +

+Why is my nil error value not equal to nil? +

+ +

+Under the covers, interfaces are implemented as two elements, a type and a value. +The value, called the interface's dynamic value, +is an arbitrary concrete value and the type is that of the value. +For the int value 3, an interface value contains, +schematically, (int, 3). +

+ +

+An interface value is nil only if the inner value and type are both unset, +(nil, nil). +In particular, a nil interface will always hold a nil type. +If we store a pointer of type *int inside +an interface value, the inner type will be *int regardless of the value of the pointer: +(*int, nil). +Such an interface value will therefore be non-nil +even when the pointer inside is nil. +

+ +

+This situation can be confusing, and often arises when a nil value is +stored inside an interface value such as an error return: +

+ +
+func returnsError() error {
+	var p *MyError = nil
+	if bad() {
+		p = ErrBad
+	}
+	return p // Will always return a non-nil error.
+}
+
+ +

+If all goes well, the function returns a nil p, +so the return value is an error interface +value holding (*MyError, nil). +This means that if the caller compares the returned error to nil, +it will always look as if there was an error even if nothing bad happened. +To return a proper nil error to the caller, +the function must return an explicit nil: +

+ + +
+func returnsError() error {
+	if bad() {
+		return ErrBad
+	}
+	return nil
+}
+
+ +

+It's a good idea for functions +that return errors always to use the error type in +their signature (as we did above) rather than a concrete type such +as *MyError, to help guarantee the error is +created correctly. As an example, +os.Open +returns an error even though, if not nil, +it's always of concrete type +*os.PathError. +

+ +

+Similar situations to those described here can arise whenever interfaces are used. +Just keep in mind that if any concrete value +has been stored in the interface, the interface will not be nil. +For more information, see +this blog post. +

+ +

Why are there no untagged unions, as in C?