diff --git a/doc/effective_go.html b/doc/effective_go.html index 21aa4cf82a..fc65d155d2 100644 --- a/doc/effective_go.html +++ b/doc/effective_go.html @@ -1,6 +1,6 @@ - +
-The Go package sources +The Go package sources are intended to serve not only as the core library but also as examples of how to use the language. @@ -1551,7 +1551,7 @@ type Handler interface {
For brevity, let's ignore POSTs and assume HTTP requests are always GETs; that simplification does not affect the way the handlers are -made. Here's a trivial but complete implementation of a handler to +set up. Here's a trivial but complete implementation of a handler to count the number of times the page is visited.
@@ -1568,7 +1568,7 @@ func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) {
(Keeping with our theme, note how Fprintf can print to an HTTP connection.)
-For reference, here's how to set up such a server.
+For reference, here's how to attach such a server to a node on the URL tree.
import "http" ... @@ -1595,17 +1595,17 @@ has been visited? Tie a channel to the web page.// A channel that sends a notification on each visit. // (Probably want the channel to be buffered.) -type Chan chan int +type Chan chan *http.Request func (ch Chan) ServeHTTP(c *http.Conn, req *http.Request) { - ch <- 1; + ch <- req; fmt.Fprint(c, "notification sent"); }Finally, let's say we wanted to present on
/argsthe arguments used when invoking the server binary. -It's easy to write a function to print the arguments: +It's easy to write a function to print the arguments.func ArgServer() { @@ -1617,8 +1617,8 @@ func ArgServer() {How do we turn that into an HTTP server? We could make
ArgServera method of some type whose value we ignore, but there's a cleaner way. -Since we can write a method for (almost) any type, we can write a method -for a function. +Since we can define a method for any type except pointers and interfaces, +we can write a method for a function. Thehttppackage contains this code:@@ -1641,8 +1641,8 @@ callsf. That may seem odd but it's no different from, say, the receiver being a channel and the method sending on the channel.-To make
ArgServerinto an HTTP server, we first give it the right -signature. +To makeArgServerinto an HTTP server, we first modify it +to have the right signature.// Argument server. @@ -1653,30 +1653,134 @@ func ArgServer(c *http.Conn, req *http.Request) { }-
ArgServerhas same signature asHandlerFunc, -so the function can be converted to that type to access its methods, -just as we convertedSequenceto[]intearlier. -The code to set it up is short: +ArgServernow has same signature asHandlerFunc, +so it can be converted to that type to access its methods, +just as we convertedSequencetoIntArray+to accessIntArray.Sort. +The code to set it up is concise:http.Handle("/args", http.HandlerFunc(ArgServer));When someone visits the page
/args, -the handler installed at that page has type -HandlerFuncand valueArgServer. +the handler installed at that page has valueArgServer+and typeHandlerFunc. The HTTP server will invoke the methodServeHTTP-of that type, with that receiver, which will in turn call +of that type, withArgServeras the receiver, which will in turn callArgServer(via the invocationf(c, req)-insideHandlerFunc.ServeHTTP) and the arguments -will be displayed. +insideHandlerFunc.ServeHTTP). +The arguments will then be displayed.-In summary, we have made an HTTP server from a struct, an integer, +In this section we have made an HTTP server from a struct, an integer, a channel, and a function, all because interfaces are just sets of methods, which can be defined for (almost) any type.
+Embedding
+ ++Go does not provide the typical, type-driven notion of subclassing, +but it does have the ability to “borrow” pieces of an +implementation by embedding types within a struct or +interface. +
++Interface embedding is very simple. +We've mentioned the
+io.Readerandio.Writerinterfaces before; +here are their definitions. ++type Reader interface { + Read(p []byte) (n int, err os.Error); +} + +type Writer interface { + Write(p []byte) (n int, err os.Error); +} +++The
+iopackage also exports several other interfaces +that specify objects that can implement several such methods. +For instance, there isio.ReadWriter, an interface +containing bothReadandWrite. +We could specifyio.ReadWriterby listing the +two methods explicitly, but it's easier and more evocative +to embed the two interfaces to form the new one, like this: ++// ReadWrite is the interface that groups the basic Read and Write methods. +type ReadWriter interface { + Reader; + Writer; +} +++This says just what it looks like: A
ReadWritercan do +what aReaderdoes and what aWriter+does; it is a union of the embedded interfaces (which must be disjoint +sets of methods). +Only interfaces can be embedded within interfaces. ++The same basic idea applies to structs, but with more far-reaching +implications. The
+bufiopackage has two struct types, +bufio.Readerandbufio.Writer, each of +which of course implements the analogous interfaces from package +io. +Andbufioalso implements a buffered reader/writer, +which it does by combining a reader and a writer into one struct +using embedding: it lists the types within the struct +but does not give them field names. ++// ReadWriter stores pointers to a Reader and a Writer. +// It implements io.ReadWriter. +type ReadWriter struct { + *Reader; + *Writer; +} +++This struct could be written as +
++type ReadWriter struct { + reader *Reader; + writer *Writer; +} +++but then to promote the methods of the fields and to +satisfy the
+iointerfaces, we would also need +to provide forwarding methods, like this: ++func (rw *ReadWriter) Read(p []byte) (n int, err os.Error) { + return rw.reader.Read(p) +} +++By embedding the structs directly, we avoid this bookkeeping. +The methods of embedded types come along for free, which means that
+bufio.ReadWriter+not only has the methods ofbufio.Readerandbufio.Writer, +it also satisfies all three interfaces: +io.Reader, +io.Writer, and +io.ReadWriter. ++There's one important way in which embedding differs from subclassing. When we embed a type, +the methods of that type become methods of the out type +
+ + +Read method of a bufio.ReadWriteris +invoked, it has the exactly the same effect as the forwarding method written out above; +the receiver is thereaderfield of theReadWriter, not the +ReadWriteritself. +Errors
@@ -1735,7 +1839,7 @@ field for recoverable failures.
for try := 0; try < 2; try++ { - file, err := os.Open(filename, os.O_RDONLY, 0); + file, err = os.Open(filename, os.O_RDONLY, 0); if err == nil { return }