content: expand discussion of interfaces

Change-Id: Ib1463519bac971b5b19952ca366de8bad58c25d7
Reviewed-on: https://go-review.googlesource.com/18425
Reviewed-by: Rob Pike <r@golang.org>
diff --git a/content/methods.article b/content/methods.article
index 9319062..ec99b7e 100644
--- a/content/methods.article
+++ b/content/methods.article
@@ -142,29 +142,131 @@
 
 * Interfaces
 
-An interface type is defined by a set of methods.
+An _interface_type_ is defined as a set of method signatures.
 
 A value of interface type can hold any value that implements those methods.
 
 *Note:* There is an error in the example code on line 22.
-`Vertex` (the value type) doesn't satisfy `Abser` because	
+`Vertex` (the value type) doesn't implement `Abser` because
 the `Abs` method is defined only on `*Vertex` (the pointer type).
 
 .play methods/interfaces.go
 
-* Interfaces are satisfied implicitly
+* Interfaces are implemented implicitly
 
-A type implements an interface by implementing the methods.
-There is no explicit declaration of intent; no "implements" keyword. 
+A type implements an interface by implementing its methods.
+There is no explicit declaration of intent, no "implements" keyword.
 
-Implicit interfaces decouple implementation packages from the packages that define the interfaces: neither depends on the other.
-
-It also encourages the definition of precise interfaces, because you don't have to find every implementation and tag it with the new interface name.
-
-[[https://golang.org/pkg/io/][Package io]] defines `Reader` and `Writer`; you don't have to.
+Implicit interfaces decouple the definition of an interface from its
+implementation, which could then appear in any package without prearrangement.
 
 .play methods/interfaces-are-satisfied-implicitly.go
 
+* Interface values
+
+Under the covers, interface values can be thought of as a tuple of a value and a
+concrete type:
+
+	(value, type)
+
+An interface value holds a value of a specific underlying concrete type.
+
+Calling a method on an interface value executes the method of the same name on
+its underlying type.
+
+.play methods/interface-values.go
+
+* Interface values with nil underlying values
+
+If the concrete value inside the interface itself is nil,
+the method will be called with a nil receiver.
+
+In some languages this would trigger a null pointer exception,
+but in Go it is common to write methods that gracefully handle being called
+with a nil receiver (as with the method `M` in this example.)
+
+Note that an interface value that holds a nil concrete value is itself non-nil.
+
+.play methods/interface-values-with-nil.go
+
+* Nil interface values
+
+A nil interface value holds neither value nor concrete type.
+
+Calling a method on a nil interface is a run-time error because there is no
+type inside the interface tuple to indicate which _concrete_ method to call.
+
+.play methods/nil-interface-values.go
+
+* The empty interface
+
+The interface type that specifies zero methods is known as the _empty_interface_:
+
+	interface{}
+
+An empty interface may hold values of any type.
+(Every type implements at least zero methods.)
+
+Empty interfaces are used by code that handles values of unknown type.
+For example, `fmt.Print` takes any number of arguments of type `interface{}`.
+
+.play methods/empty-interface.go
+
+* Type assertions
+
+A _type_assertion_ provides access to an interface value's underlying concrete value.
+
+	t := i.(T)
+
+This statement asserts that the interface value `i` holds the concrete type `T`
+and assigns the underlying `T` value to the variable `t`.
+
+If `i` does not hold a `T`, the statement will trigger a panic.
+
+To _test_ whether an interface value holds a specific type,
+a type assertion can return two values: the underlying value
+and a boolean value that reports whether the assertion succeeded.
+
+	t, ok := i.(T)
+
+If `i` holds a `T`, then `t` will be the underlying value and `ok` will be true.
+
+If not, `ok` will be false and `t` will be the zero value of type `T`,
+and no panic occurs.
+
+Note the similarity between this syntax and that of reading from a map.
+
+.play methods/type-assertions.go
+
+* Type switches
+
+A _type_switch_ is a construct that permits several type assertions in series.
+
+A type switch is like a regular switch statement, but the cases in a type
+switch specify types (not values), and those values are compared against
+the type of the value held by the given interface value.
+
+	switch v := i.(type) {
+	case T:
+		// here v has type T
+	case S:
+		// here v has type S
+	default:
+		// no match; here v has the same type as i
+	}
+
+The declaration in a type switch has the same syntax as a type assertion `i.(T)`,
+but the specific type `T` is replaced with the keyword `type`.
+
+This switch statement tests whether the interface value `i`
+holds a value of type `T` or `S`.
+In each of the `T` and `S` cases, the variable `v` will be of type
+`T` or `S` respectively and hold the value held by `i`.
+In the default case (where there is no match), the variable `v` is
+of the same interface type and value as `i`.
+
+.play methods/type-switches.go
+
 * Stringers
 
 One of the most ubiquitous interfaces is [[//golang.org/pkg/fmt/#Stringer][`Stringer`]] defined by the [[//golang.org/pkg/fmt/][`fmt`]] package.
@@ -277,56 +379,6 @@
 
 .play methods/exercise-rot-reader.go
 
-* Web servers
-
-[[https://golang.org/pkg/net/http/][Package http]] serves HTTP requests using any value that implements `http.Handler`:
-
-	package http
-
-	type Handler interface {
-		ServeHTTP(w ResponseWriter, r *Request)
-	}
-
-In this example, the type `Hello` implements `http.Handler`.
-
-Visit [[http://localhost:4000/][http://localhost:4000/]] to see the greeting.
-
-#appengine: *Note:* This example won't run through the web-based tour user
-#appengine: interface. To try writing web servers you may want to
-#appengine: [[https://golang.org/dl/][Install Go]].
-
-.play methods/web-servers.go
-
-* Exercise: HTTP Handlers
-
-Implement the following types and define ServeHTTP methods on them. Register them to handle specific paths in your web server.
-
-	type String string
-
-	type Struct struct {
-		Greeting string
-		Punct    string
-		Who      string
-	}
-
-For example, you should be able to register handlers using:
-
-	http.Handle("/string", String("I'm a frayed knot."))
-	http.Handle("/struct", &Struct{"Hello", ":", "Gophers!"})
-
-After starting your server, you will be able to visit
-[[http://localhost:4000/string][http://localhost:4000/string]] and
-[[http://localhost:4000/struct][http://localhost:4000/struct]].
-
-For more details about the `http.Handle` function, see
-[[https://golang.org/pkg/net/http/#Handle][the documentation]].
-
-#appengine: *Note:* This example won't run through the web-based tour user
-#appengine: interface. To try writing web servers you may want to
-#appengine: [[https://golang.org/dl/][Install Go]].
-
-.play methods/exercise-http-handlers.go
-
 * Images
 
 [[https://golang.org/pkg/image/#Image][Package image]] defines the `Image` interface:
diff --git a/content/methods/empty-interface.go b/content/methods/empty-interface.go
new file mode 100644
index 0000000..10e9861
--- /dev/null
+++ b/content/methods/empty-interface.go
@@ -0,0 +1,20 @@
+// +build OMIT
+
+package main
+
+import "fmt"
+
+func main() {
+	var i interface{}
+	describe(i)
+
+	i = 42
+	describe(i)
+
+	i = "hello"
+	describe(i)
+}
+
+func describe(i interface{}) {
+	fmt.Printf("(%v, %T)\n", i, i)
+}
diff --git a/content/methods/exercise-http-handlers.go b/content/methods/exercise-http-handlers.go
deleted file mode 100644
index a824531..0000000
--- a/content/methods/exercise-http-handlers.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// +build OMIT
-
-package main
-
-import (
-	"log"
-	"net/http"
-)
-
-func main() {
-	// your http.Handle calls here
-	log.Fatal(http.ListenAndServe("localhost:4000", nil))
-}
diff --git a/content/methods/interface-values-with-nil.go b/content/methods/interface-values-with-nil.go
new file mode 100644
index 0000000..60d69d5
--- /dev/null
+++ b/content/methods/interface-values-with-nil.go
@@ -0,0 +1,38 @@
+// build +OMIT
+
+package main
+
+import "fmt"
+
+type I interface {
+	M()
+}
+
+type T struct {
+	S string
+}
+
+func (t *T) M() {
+	if t == nil {
+		fmt.Println("<nil>")
+		return
+	}
+	fmt.Println(t.S)
+}
+
+func main() {
+	var i I
+
+	var t *T
+	i = t
+	describe(i)
+	i.M()
+
+	i = &T{"hello"}
+	describe(i)
+	i.M()
+}
+
+func describe(i I) {
+	fmt.Printf("(%v, %T)\n", i, i)
+}
diff --git a/content/methods/interface-values.go b/content/methods/interface-values.go
new file mode 100644
index 0000000..52d2b3d
--- /dev/null
+++ b/content/methods/interface-values.go
@@ -0,0 +1,42 @@
+// build +OMIT
+
+package main
+
+import (
+	"fmt"
+	"math"
+)
+
+type I interface {
+	M()
+}
+
+type T struct {
+	S string
+}
+
+func (t *T) M() {
+	fmt.Println(t.S)
+}
+
+type F float64
+
+func (f F) M() {
+	fmt.Println(f)
+}
+
+func main() {
+	var i I
+
+	i = &T{"Hello"}
+	describe(i)
+	i.M()
+
+	i = F(math.Pi)
+	describe(i)
+	i.M()
+}
+
+func describe(i I) {
+	fmt.Printf("(%v, %T)\n", i, i)
+}
diff --git a/content/methods/interfaces-are-satisfied-implicitly.go b/content/methods/interfaces-are-satisfied-implicitly.go
index d7f2589..4bc2232 100644
--- a/content/methods/interfaces-are-satisfied-implicitly.go
+++ b/content/methods/interfaces-are-satisfied-implicitly.go
@@ -2,29 +2,23 @@
 
 package main
 
-import (
-	"fmt"
-	"os"
-)
+import "fmt"
 
-type Reader interface {
-	Read(b []byte) (n int, err error)
+type I interface {
+	M()
 }
 
-type Writer interface {
-	Write(b []byte) (n int, err error)
+type T struct {
+	S string
 }
 
-type ReadWriter interface {
-	Reader
-	Writer
+// This method means type T implements the interface I,
+// but we don't need to explicitly declare that it does so.
+func (t T) M() {
+	fmt.Println(t.S)
 }
 
 func main() {
-	var w Writer
-
-	// os.Stdout implements Writer
-	w = os.Stdout
-
-	fmt.Fprintf(w, "hello, writer\n")
+	var i I = &T{"hello"}
+	i.M()
 }
diff --git a/content/methods/nil-interface-values.go b/content/methods/nil-interface-values.go
new file mode 100644
index 0000000..e15bdc9
--- /dev/null
+++ b/content/methods/nil-interface-values.go
@@ -0,0 +1,19 @@
+// build +OMIT
+
+package main
+
+import "fmt"
+
+type I interface {
+	M()
+}
+
+func main() {
+	var i I
+	describe(i)
+	i.M()
+}
+
+func describe(i I) {
+	fmt.Printf("(%v, %T)\n", i, i)
+}
diff --git a/content/methods/type-assertions.go b/content/methods/type-assertions.go
new file mode 100644
index 0000000..fcd5685
--- /dev/null
+++ b/content/methods/type-assertions.go
@@ -0,0 +1,21 @@
+// build +OMIT
+
+package main
+
+import "fmt"
+
+func main() {
+	var i interface{} = "hello"
+
+	s := i.(string)
+	fmt.Println(s)
+
+	s, ok := i.(string)
+	fmt.Println(s, ok)
+
+	f, ok := i.(float64)
+	fmt.Println(f, ok)
+
+	f = i.(float64) // panic
+	fmt.Println(f)
+}
diff --git a/content/methods/type-switches.go b/content/methods/type-switches.go
new file mode 100644
index 0000000..12d879d
--- /dev/null
+++ b/content/methods/type-switches.go
@@ -0,0 +1,22 @@
+// +build OMIT
+
+package main
+
+import "fmt"
+
+func do(i interface{}) {
+	switch v := i.(type) {
+	case int:
+		fmt.Printf("Twice %v is %v\n", v, v*2)
+	case string:
+		fmt.Printf("%q is %v bytes long\n", v, len(v))
+	default:
+		fmt.Printf("I don't know about type %T!\n", v)
+	}
+}
+
+func main() {
+	do(21)
+	do("hello")
+	do(true)
+}
diff --git a/content/methods/web-servers.go b/content/methods/web-servers.go
deleted file mode 100644
index eff055a..0000000
--- a/content/methods/web-servers.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// +build OMIT
-
-package main
-
-import (
-	"fmt"
-	"log"
-	"net/http"
-)
-
-type Hello struct{}
-
-func (h Hello) ServeHTTP(
-	w http.ResponseWriter,
-	r *http.Request) {
-	fmt.Fprint(w, "Hello!")
-}
-
-func main() {
-	var h Hello
-	err := http.ListenAndServe("localhost:4000", h)
-	if err != nil {
-		log.Fatal(err)
-	}
-}