diff --git a/doc/go_faq.html b/doc/go_faq.html index 93e1ea4ee5..36e1e53e58 100644 --- a/doc/go_faq.html +++ b/doc/go_faq.html @@ -680,6 +680,85 @@ for i, v := range t { } +
+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.
+