mirror of
https://github.com/golang/go
synced 2024-11-22 00:54:43 -07:00
interfaces and methods.
R=rsc DELTA=160 (143 added, 5 deleted, 12 changed) OCL=35748 CL=35758
This commit is contained in:
parent
b83549a7e6
commit
2119b3672d
@ -310,11 +310,12 @@ which is a clear, concise name.
|
||||
Moreover,
|
||||
because imported entities are always addressed with their package name, <code>bufio.Reader</code>
|
||||
does not conflict with <code>io.Reader</code>.
|
||||
Similarly, the constructor for <code>vector.Vector</code>
|
||||
would normally be called <code>NewVector</code> but since
|
||||
Similarly, the function to make new instances of <code>vector.Vector</code>
|
||||
—which is the definition of a <em>constructor</em> in Go—would
|
||||
normally be called <code>NewVector</code> but since
|
||||
<code>Vector</code> is the only type exported by the package, and since the
|
||||
package is called <code>vector</code>, it's called just <code>New</code>,
|
||||
which clients of the package see as <code>vector.New</code>.
|
||||
package is called <code>vector</code>, it's called just <code>New</code>.
|
||||
Clients of the package see that as <code>vector.New</code>.
|
||||
Use the package structure to help you choose good names.
|
||||
</p>
|
||||
|
||||
@ -1372,7 +1373,7 @@ By the way, the idea of using <code>Write</code> on a slice of bytes
|
||||
is implemented by <code>bytes.Buffer</code>.
|
||||
</p>
|
||||
|
||||
<h2 id="interfaces_and_types">Interfaces and the interplay of types</h2>
|
||||
<h2 id="interfaces_and_types">Interfaces and other types</h2>
|
||||
|
||||
<h3 id="interfaces">Interfaces</h3>
|
||||
<p>
|
||||
@ -1382,7 +1383,7 @@ object: if something can do <em>this</em>, then it can be used
|
||||
custom printers can be implemented by a <code>String</code> method
|
||||
while <code>Fprintf</code> can generate output to anything
|
||||
with a <code>Write</code> method.
|
||||
Interfaces with only one or two methods are common in Go, and are
|
||||
Interfaces with only one or two methods are common in Go code, and are
|
||||
usually given a name derived from the method, such as <code>io.Writer</code>
|
||||
for something that implements <code>Write</code>.
|
||||
</p>
|
||||
@ -1477,10 +1478,11 @@ That's more unusual in practice but can be effective.
|
||||
<p>
|
||||
If a type exists only to implement an interface
|
||||
and has no exported methods beyond that interface,
|
||||
there is no need to publish the type itself.
|
||||
Publishing just the interface makes it easy for
|
||||
other implementations with different properties
|
||||
to mirror the job of the original type.
|
||||
there is no need to export the type itself.
|
||||
Exporting just the interface makes it clear that
|
||||
it's the behavior that matters, not the implementation,
|
||||
and that other implementations with different properties
|
||||
can mirror the behavior of the original type.
|
||||
It also avoids the need to repeat the documentation
|
||||
on every instance of a common method.
|
||||
</p>
|
||||
@ -1502,7 +1504,7 @@ By analogy to the <code>bufio</code> package,
|
||||
they wrap a <code>Cipher</code> interface
|
||||
and they return <code>hash.Hash</code>,
|
||||
<code>io.Reader</code>, or <code>io.Writer</code>
|
||||
interface values, not direct implementations.
|
||||
interface values, not specific implementations.
|
||||
</p>
|
||||
<p>
|
||||
The interface to <code>crypto/block</code> includes:
|
||||
@ -1534,6 +1536,147 @@ calls must be edited, but because the code must treat the result only
|
||||
as an <code>io.Reader</code>, it won't notice the difference.
|
||||
</p>
|
||||
|
||||
<h3 id="interface_methods">Interfaces and methods</h3>
|
||||
<p>
|
||||
Since almost anything can have methods attached, almost anything can
|
||||
satisfy an interface. One illustrative example is in the <code>http</code>
|
||||
package, which defines the <code>Handler</code> interface. Any object
|
||||
that implements <code>Handler</code> can serve HTTP requests.
|
||||
</p>
|
||||
<pre>
|
||||
type Handler interface {
|
||||
ServeHTTP(*Conn, *Request);
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
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
|
||||
count the number of times the
|
||||
page is visited.
|
||||
</p>
|
||||
<pre>
|
||||
// Simple counter server.
|
||||
type Counter struct {
|
||||
n int;
|
||||
}
|
||||
|
||||
func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) {
|
||||
ctr.n++;
|
||||
fmt.Fprintf(c, "counter = %d\n", ctr.n);
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
(Keeping with our theme, note how <code>Fprintf</code> can print to an HTTP connection.)
|
||||
For reference, here's how to set up such a server.
|
||||
<pre>
|
||||
import "http"
|
||||
...
|
||||
ctr := new(Counter);
|
||||
http.Handle("/counter", ctr);
|
||||
</pre>
|
||||
<p>
|
||||
But why make <code>Counter</code> a struct? An integer is all that's needed.
|
||||
(The receiver needs to be a pointer so the increment is visible to the caller.)
|
||||
</p>
|
||||
<pre>
|
||||
// Simpler counter server.
|
||||
type Counter int
|
||||
|
||||
func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) {
|
||||
ctr++;
|
||||
fmt.Fprintf(c, "counter = %d\n", ctr);
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
What if your program has some internal state that needs to be notified that a page
|
||||
has been visited? Tie a channel to the web page.
|
||||
</p>
|
||||
<pre>
|
||||
// A channel that sends a notification on each visit.
|
||||
// (Probably want the channel to be buffered.)
|
||||
type Chan chan int
|
||||
|
||||
func (ch Chan) ServeHTTP(c *http.Conn, req *http.Request) {
|
||||
ch <- 1;
|
||||
fmt.Fprint(c, "notification sent");
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Finally, let's say we wanted to present on <code>/args</code> the arguments
|
||||
used when invoking the server binary.
|
||||
It's easy to write a function to print the arguments:
|
||||
</p>
|
||||
<pre>
|
||||
func ArgServer() {
|
||||
for i, s := range os.Args {
|
||||
fmt.Println(s);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
How do we turn that into an HTTP server? We could make <code>ArgServer</code>
|
||||
a 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.
|
||||
The <code>http</code> package contains this code:
|
||||
</p>
|
||||
<pre>
|
||||
// The HandlerFunc type is an adapter to allow the use of
|
||||
// ordinary functions as HTTP handlers. If f is a function
|
||||
// with the appropriate signature, HandlerFunc(f) is a
|
||||
// Handler object that calls f.
|
||||
type HandlerFunc func(*Conn, *Request)
|
||||
|
||||
// ServeHTTP calls f(c, req).
|
||||
func (f HandlerFunc) ServeHTTP(c *Conn, req *Request) {
|
||||
f(c, req);
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
<code>HandlerFunc</code> is a type with a method, <code>ServeHTTP</code>,
|
||||
so values of that type can serve HTTP requests. Look at the implementation
|
||||
of the method: the receiver is a function, <code>f</code>, and the method
|
||||
calls <code>f</code>. That may seem odd but it's no different from, say,
|
||||
the receiver being a channel and the method sending on the channel.
|
||||
</p>
|
||||
<p>
|
||||
To make <code>ArgServer</code> into an HTTP server, we first give it the right
|
||||
signature.
|
||||
</p>
|
||||
<pre>
|
||||
// Argument server.
|
||||
func ArgServer(c *http.Conn, req *http.Request) {
|
||||
for i, s := range os.Args {
|
||||
fmt.Fprintln(c, s);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
<code>ArgServer</code> has same signature as <code>HandlerFunc</code>,
|
||||
so the function can be converted to that type to access its methods,
|
||||
just as we converted <code>Sequence</code> to <code>[]int</code> earlier.
|
||||
The code to set it up is short:
|
||||
</p>
|
||||
<pre>
|
||||
http.Handle("/args", http.HandlerFunc(ArgServer));
|
||||
</pre>
|
||||
<p>
|
||||
When someone visits the page <code>/args</code>,
|
||||
the handler installed at that page has type
|
||||
<code>HandlerFunc</code> and value <code>ArgServer</code>.
|
||||
The HTTP server will invoke the method <code>ServeHTTP</code>
|
||||
of that type, with that receiver, which will in turn call
|
||||
<code>ArgServer</code> (via the invocation <code>f(c, req)</code>
|
||||
inside <code>HandlerFunc.ServeHTTP</code>) and the arguments
|
||||
will be displayed.
|
||||
</p>
|
||||
<p>
|
||||
In summary, 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.
|
||||
</p>
|
||||
|
||||
<h2 id="errors">Errors</h2>
|
||||
|
||||
<p>
|
||||
@ -1604,8 +1747,6 @@ for try := 0; try < 2; try++ {
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2>Testing</h2>
|
||||
|
||||
<h2>More to come</h2>
|
||||
|
||||
<!---
|
||||
@ -1696,10 +1837,7 @@ used by both <code>TestEncoder</code> and <code>TestDecoder</code>.
|
||||
|
||||
<p>
|
||||
This data-driven style dominates in the Go package tests.
|
||||
<!--
|
||||
<br>
|
||||
link to go code search for 'for.*range' here
|
||||
-->
|
||||
<font color="red">((link to go code search for 'for.*range' here))</font>
|
||||
</p>
|
||||
|
||||
<h3 id="reflect.DeepEqual">Use reflect.DeepEqual to compare complex values</h3>
|
||||
|
Loading…
Reference in New Issue
Block a user