summaryrefslogtreecommitdiff
path: root/doc/go_tutorial.html
diff options
context:
space:
mode:
Diffstat (limited to 'doc/go_tutorial.html')
-rw-r--r--doc/go_tutorial.html176
1 files changed, 88 insertions, 88 deletions
diff --git a/doc/go_tutorial.html b/doc/go_tutorial.html
index 822f9626e..0b366bb2b 100644
--- a/doc/go_tutorial.html
+++ b/doc/go_tutorial.html
@@ -19,17 +19,14 @@ The presentation here proceeds through a series of modest programs to illustrate
key features of the language. All the programs work (at time of writing) and are
checked into the repository in the directory <a href='/doc/progs'><code>/doc/progs/</code></a>.
<p>
-Program snippets are annotated with the line number in the original file; for
-cleanliness, blank lines remain blank.
-<p>
<h2>Hello, World</h2>
<p>
Let's start in the usual way:
<p>
-<pre><!-- progs/helloworld.go /package/ $
+<pre><!--{{code "progs/helloworld.go" `/package/` "$"}}
-->package main
-import fmt &#34;fmt&#34; // Package implementing formatted I/O.
+import fmt &#34;fmt&#34; // Package implementing formatted I/O.
func main() {
fmt.Printf(&#34;Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n&#34;)
@@ -116,23 +113,23 @@ $
<p>
Next up, here's a version of the Unix utility <code>echo(1)</code>:
<p>
-<pre><!-- progs/echo.go /package/ $
+<pre><!--{{code "progs/echo.go" `/package/` "$"}}
-->package main
import (
&#34;os&#34;
- &#34;flag&#34; // command line option parser
+ &#34;flag&#34; // command line option parser
)
var omitNewline = flag.Bool(&#34;n&#34;, false, &#34;don&#39;t print final newline&#34;)
const (
- Space = &#34; &#34;
+ Space = &#34; &#34;
Newline = &#34;\n&#34;
)
func main() {
- flag.Parse() // Scans the arg list and sets up flags
+ flag.Parse() // Scans the arg list and sets up flags
var s string = &#34;&#34;
for i := 0; i &lt; flag.NArg(); i++ {
if i &gt; 0 {
@@ -176,12 +173,13 @@ a naming conflict.
<p>
Given <code>os.Stdout</code> we can use its <code>WriteString</code> method to print the string.
<p>
-Having imported the <code>flag</code> package, line 12 creates a global variable to hold
-the value of echo's <code>-n</code> flag. The variable <code>omitNewline</code> has type <code>*bool</code>, pointer
-to <code>bool</code>.
+After importing the <code>flag</code> package, we use a <code>var</code> declaration
+to create and initialize a global variable, called <code>omitNewline</code>,
+to hold the value of echo's <code>-n</code> flag.
+The variable has type <code>*bool</code>, pointer to <code>bool</code>.
<p>
-In <code>main.main</code>, we parse the arguments (line 20) and then create a local
-string variable we will use to build the output.
+In <code>main.main</code>, we parse the arguments (the call to <code>flag.Parse</code>) and then create a local
+string variable with which to build the output.
<p>
The declaration statement has the form
<p>
@@ -209,7 +207,7 @@ s := ""
The <code>:=</code> operator is used a lot in Go to represent an initializing declaration.
There's one in the <code>for</code> clause on the next line:
<p>
-<pre><!-- progs/echo.go /for/
+<pre><!--{{code "progs/echo.go" `/for/`}}
--> for i := 0; i &lt; flag.NArg(); i++ {
</pre>
<p>
@@ -259,9 +257,11 @@ Once you've built a string <i>value</i>, you can't change it, although
of course you can change a string <i>variable</i> simply by
reassigning it. This snippet from <code>strings.go</code> is legal code:
<p>
-<pre><!-- progs/strings.go /hello/ /ciao/
+<pre><!--{{code "progs/strings.go" `/hello/` `/ciao/`}}
--> s := &#34;hello&#34;
- if s[1] != 'e' { os.Exit(1) }
+ if s[1] != &#39;e&#39; {
+ os.Exit(1)
+ }
s = &#34;good bye&#34;
var p *string = &amp;s
*p = &#34;ciao&#34;
@@ -330,7 +330,7 @@ will slice the whole array.
<p>
Using slices one can write this function (from <code>sum.go</code>):
<p>
-<pre><!-- progs/sum.go /sum/ /^}/
+<pre><!--{{code "progs/sum.go" `/sum/` `/^}/`}}
-->func sum(a []int) int { // returns an int
s := 0
for i := 0; i &lt; len(a); i++ {
@@ -476,7 +476,7 @@ assigned to a variable.
Next we'll look at a simple package for doing file I/O with an
open/close/read/write interface. Here's the start of <code>file.go</code>:
<p>
-<pre><!-- progs/file.go /package/ /^}/
+<pre><!--{{code "progs/file.go" `/package/` `/^}/`}}
-->package file
import (
@@ -518,7 +518,7 @@ will soon give it some exported, upper-case methods.
<p>
First, though, here is a factory to create a <code>File</code>:
<p>
-<pre><!-- progs/file.go /newFile/ /^}/
+<pre><!--{{code "progs/file.go" `/newFile/` `/^}/`}}
-->func newFile(fd int, name string) *File {
if fd &lt; 0 {
return nil
@@ -540,11 +540,11 @@ return n
</pre>
<p>
but for simple structures like <code>File</code> it's easier to return the address of a
-composite literal, as is done here on line 21.
+composite literal, as is done here in the <code>return</code> statement from <code>newFile</code>.
<p>
We can use the factory to construct some familiar, exported variables of type <code>*File</code>:
<p>
-<pre><!-- progs/file.go /var/ /^.$/
+<pre><!--{{code "progs/file.go" `/var/` `/^.$/`}}
-->var (
Stdin = newFile(syscall.Stdin, &#34;/dev/stdin&#34;)
Stdout = newFile(syscall.Stdout, &#34;/dev/stdout&#34;)
@@ -556,7 +556,7 @@ We can use the factory to construct some familiar, exported variables of type <c
The <code>newFile</code> function was not exported because it's internal. The proper,
exported factory to use is <code>OpenFile</code> (we'll explain that name in a moment):
<p>
-<pre><!-- progs/file.go /func.OpenFile/ /^}/
+<pre><!--{{code "progs/file.go" `/func.OpenFile/` `/^}/`}}
-->func OpenFile(name string, mode int, perm uint32) (file *File, err os.Error) {
r, e := syscall.Open(name, mode, perm)
if e != 0 {
@@ -573,9 +573,9 @@ multi-value return as a parenthesized list of declarations; syntactically
they look just like a second parameter list. The function
<code>syscall.Open</code>
also has a multi-value return, which we can grab with the multi-variable
-declaration on line 31; it declares <code>r</code> and <code>e</code> to hold the two values,
+declaration on the first line; it declares <code>r</code> and <code>e</code> to hold the two values,
both of type <code>int</code> (although you'd have to look at the <code>syscall</code> package
-to see that). Finally, line 35 returns two values: a pointer to the new <code>File</code>
+to see that). Finally, <code>OpenFile</code> returns two values: a pointer to the new <code>File</code>
and the error. If <code>syscall.Open</code> fails, the file descriptor <code>r</code> will
be negative and <code>newFile</code> will return <code>nil</code>.
<p>
@@ -594,7 +594,7 @@ the implementation of our <code>Open</code> and <code>Create</code>; they're tri
wrappers that eliminate common errors by capturing
the tricky standard arguments to open and, especially, to create a file:
<p>
-<pre><!-- progs/file.go /^const/ /^}/
+<pre><!--{{code "progs/file.go" `/^const/` `/^}/`}}
-->const (
O_RDONLY = syscall.O_RDONLY
O_RDWR = syscall.O_RDWR
@@ -607,7 +607,7 @@ func Open(name string) (file *File, err os.Error) {
}
</pre>
<p>
-<pre><!-- progs/file.go /func.Create/ /^}/
+<pre><!--{{code "progs/file.go" `/func.Create/` `/^}/`}}
-->func Create(name string) (file *File, err os.Error) {
return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}
@@ -620,13 +620,13 @@ of that type, placed
in parentheses before the function name. Here are some methods for <code>*File</code>,
each of which declares a receiver variable <code>file</code>.
<p>
-<pre><!-- progs/file.go /Close/ $
+<pre><!--{{code "progs/file.go" `/Close/` "$"}}
-->func (file *File) Close() os.Error {
if file == nil {
return os.EINVAL
}
e := syscall.Close(file.fd)
- file.fd = -1 // so it can't be closed again
+ file.fd = -1 // so it can&#39;t be closed again
if e != 0 {
return os.Errno(e)
}
@@ -675,7 +675,7 @@ set of such error values.
<p>
We can now use our new package:
<p>
-<pre><!-- progs/helloworld3.go /package/ $
+<pre><!--{{code "progs/helloworld3.go" `/package/` "$"}}
-->package main
import (
@@ -689,7 +689,7 @@ func main() {
file.Stdout.Write(hello)
f, err := file.Open(&#34;/does/not/exist&#34;)
if f == nil {
- fmt.Printf(&#34;can&#39;t open file; err=%s\n&#34;, err.String())
+ fmt.Printf(&#34;can&#39;t open file; err=%s\n&#34;, err.String())
os.Exit(1)
}
}
@@ -718,7 +718,7 @@ $
Building on the <code>file</code> package, here's a simple version of the Unix utility <code>cat(1)</code>,
<code>progs/cat.go</code>:
<p>
-<pre><!-- progs/cat.go /package/ $
+<pre><!--{{code "progs/cat.go" `/package/` "$"}}
-->package main
import (
@@ -790,7 +790,7 @@ The <code>cat</code> subroutine uses only two methods of <code>f</code>: <code>R
so let's start by defining an interface that has exactly those two methods.
Here is code from <code>progs/cat_rot13.go</code>:
<p>
-<pre><!-- progs/cat_rot13.go /type.reader/ /^}/
+<pre><!--{{code "progs/cat_rot13.go" `/type.reader/` `/^}/`}}
-->type reader interface {
Read(b []byte) (ret int, err os.Error)
String() string
@@ -807,7 +807,7 @@ existing <code>reader</code> and does <code>rot13</code> on the data. To do this
the type and implement the methods and with no other bookkeeping,
we have a second implementation of the <code>reader</code> interface.
<p>
-<pre><!-- progs/cat_rot13.go /type.rotate13/ /end.of.rotate13/
+<pre><!--{{code "progs/cat_rot13.go" `/type.rotate13/` `/end.of.rotate13/`}}
-->type rotate13 struct {
source reader
}
@@ -834,13 +834,13 @@ func (r13 *rotate13) String() string {
<p>
To use the new feature, we define a flag:
<p>
-<pre><!-- progs/cat_rot13.go /rot13Flag/
+<pre><!--{{code "progs/cat_rot13.go" `/rot13Flag/`}}
-->var rot13Flag = flag.Bool(&#34;rot13&#34;, false, &#34;rot13 the input&#34;)
</pre>
<p>
and use it from within a mostly unchanged <code>cat</code> function:
<p>
-<pre><!-- progs/cat_rot13.go /func.cat/ /^}/
+<pre><!--{{code "progs/cat_rot13.go" `/func.cat/` `/^}/`}}
-->func cat(r reader) {
const NBUF = 512
var buf [NBUF]byte
@@ -911,7 +911,7 @@ same interface variable.
<p>
As an example, consider this simple sort algorithm taken from <code>progs/sort.go</code>:
<p>
-<pre><!-- progs/sort.go /func.Sort/ /^}/
+<pre><!--{{code "progs/sort.go" `/func.Sort/` `/^}/`}}
-->func Sort(data Interface) {
for i := 1; i &lt; data.Len(); i++ {
for j := i; j &gt; 0 &amp;&amp; data.Less(j, j-1); j-- {
@@ -923,7 +923,7 @@ As an example, consider this simple sort algorithm taken from <code>progs/sort.g
<p>
The code needs only three methods, which we wrap into sort's <code>Interface</code>:
<p>
-<pre><!-- progs/sort.go /interface/ /^}/
+<pre><!--{{code "progs/sort.go" `/interface/` `/^}/`}}
-->type Interface interface {
Len() int
Less(i, j int) bool
@@ -935,12 +935,12 @@ We can apply <code>Sort</code> to any type that implements <code>Len</code>, <co
The <code>sort</code> package includes the necessary methods to allow sorting of
arrays of integers, strings, etc.; here's the code for arrays of <code>int</code>
<p>
-<pre><!-- progs/sort.go /type.*IntSlice/ /Swap/
+<pre><!--{{code "progs/sort.go" `/type.*IntSlice/` `/Swap/`}}
-->type IntSlice []int
-func (p IntSlice) Len() int { return len(p) }
-func (p IntSlice) Less(i, j int) bool { return p[i] &lt; p[j] }
-func (p IntSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+func (p IntSlice) Len() int { return len(p) }
+func (p IntSlice) Less(i, j int) bool { return p[i] &lt; p[j] }
+func (p IntSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
</pre>
<p>
Here we see methods defined for non-<code>struct</code> types. You can define methods
@@ -950,7 +950,7 @@ And now a routine to test it out, from <code>progs/sortmain.go</code>. This
uses a function in the <code>sort</code> package, omitted here for brevity,
to test that the result is sorted.
<p>
-<pre><!-- progs/sortmain.go /func.ints/ /^}/
+<pre><!--{{code "progs/sortmain.go" `/func.ints/` `/^}/`}}
-->func ints() {
data := []int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586}
a := sort.IntSlice(data)
@@ -964,20 +964,20 @@ to test that the result is sorted.
If we have a new type we want to be able to sort, all we need to do is
to implement the three methods for that type, like this:
<p>
-<pre><!-- progs/sortmain.go /type.day/ /Swap/
+<pre><!--{{code "progs/sortmain.go" `/type.day/` `/Swap/`}}
-->type day struct {
- num int
- shortName string
- longName string
+ num int
+ shortName string
+ longName string
}
type dayArray struct {
data []*day
}
-func (p *dayArray) Len() int { return len(p.data) }
-func (p *dayArray) Less(i, j int) bool { return p.data[i].num &lt; p.data[j].num }
-func (p *dayArray) Swap(i, j int) { p.data[i], p.data[j] = p.data[j], p.data[i] }
+func (p *dayArray) Len() int { return len(p.data) }
+func (p *dayArray) Less(i, j int) bool { return p.data[i].num &lt; p.data[j].num }
+func (p *dayArray) Swap(i, j int) { p.data[i], p.data[j] = p.data[j], p.data[i] }
</pre>
<p>
<p>
@@ -1012,8 +1012,8 @@ argument. It's easier in many cases in Go. Instead of <code>%llud</code> you
can just say <code>%d</code>; <code>Printf</code> knows the size and signedness of the
integer and can do the right thing for you. The snippet
<p>
-<pre><!-- progs/print.go 10 11
---> var u64 uint64 = 1&lt;&lt;64-1
+<pre><!--{{code "progs/print.go" 10 11}}
+--> var u64 uint64 = 1&lt;&lt;64 - 1
fmt.Printf(&#34;%d %d\n&#34;, u64, int64(u64))
</pre>
<p>
@@ -1026,7 +1026,7 @@ prints
In fact, if you're lazy the format <code>%v</code> will print, in a simple
appropriate style, any value, even an array or structure. The output of
<p>
-<pre><!-- progs/print.go 14 20
+<pre><!--{{code "progs/print.go" 14 20}}
--> type T struct {
a int
b string
@@ -1049,7 +1049,7 @@ of <code>%v</code> while <code>Println</code> inserts spaces between arguments
and adds a newline. The output of each of these two lines is identical
to that of the <code>Printf</code> call above.
<p>
-<pre><!-- progs/print.go 21 22
+<pre><!--{{code "progs/print.go" 21 22}}
--> fmt.Print(u64, &#34; &#34;, t, &#34; &#34;, a, &#34;\n&#34;)
fmt.Println(u64, t, a)
</pre>
@@ -1060,7 +1060,7 @@ routines will examine the value to inquire whether it implements
the method and if so, use it rather than some other formatting.
Here's a simple example.
<p>
-<pre><!-- progs/print_string.go 9 $
+<pre><!--{{code "progs/print_string.go" 9 "$"}}
-->type testType struct {
a int
b string
@@ -1179,11 +1179,11 @@ coordinates the communication; as with maps and slices, use
<p>
Here is the first function in <code>progs/sieve.go</code>:
<p>
-<pre><!-- progs/sieve.go /Send/ /^}/
--->// Send the sequence 2, 3, 4, ... to channel 'ch'.
+<pre><!--{{code "progs/sieve.go" `/Send/` `/^}/`}}
+-->// Send the sequence 2, 3, 4, ... to channel &#39;ch&#39;.
func generate(ch chan int) {
for i := 2; ; i++ {
- ch &lt;- i // Send &#39;i&#39; to channel &#39;ch&#39;.
+ ch &lt;- i // Send &#39;i&#39; to channel &#39;ch&#39;.
}
}
</pre>
@@ -1198,14 +1198,14 @@ channel, and a prime number. It copies values from the input to the
output, discarding anything divisible by the prime. The unary communications
operator <code>&lt;-</code> (receive) retrieves the next value on the channel.
<p>
-<pre><!-- progs/sieve.go /Copy.the/ /^}/
--->// Copy the values from channel 'in' to channel 'out',
-// removing those divisible by 'prime'.
+<pre><!--{{code "progs/sieve.go" `/Copy.the/` `/^}/`}}
+-->// Copy the values from channel &#39;in&#39; to channel &#39;out&#39;,
+// removing those divisible by &#39;prime&#39;.
func filter(in, out chan int, prime int) {
for {
- i := &lt;-in // Receive value of new variable &#39;i&#39; from &#39;in&#39;.
- if i % prime != 0 {
- out &lt;- i // Send &#39;i&#39; to channel &#39;out&#39;.
+ i := &lt;-in // Receive value of new variable &#39;i&#39; from &#39;in&#39;.
+ if i%prime != 0 {
+ out &lt;- i // Send &#39;i&#39; to channel &#39;out&#39;.
}
}
}
@@ -1236,10 +1236,10 @@ result := &lt;-ch // wait for, and retrieve, result
Back to our prime sieve. Here's how the sieve pipeline is stitched
together:
<p>
-<pre><!-- progs/sieve.go /func.main/ /^}/
+<pre><!--{{code "progs/sieve.go" `/func.main/` `/^}/`}}
-->func main() {
- ch := make(chan int) // Create a new channel.
- go generate(ch) // Start generate() as a goroutine.
+ ch := make(chan int) // Create a new channel.
+ go generate(ch) // Start generate() as a goroutine.
for i := 0; i &lt; 100; i++ { // Print the first hundred primes.
prime := &lt;-ch
fmt.Println(prime)
@@ -1259,10 +1259,10 @@ The sieve program can be tweaked to use a pattern common
in this style of programming. Here is a variant version
of <code>generate</code>, from <code>progs/sieve1.go</code>:
<p>
-<pre><!-- progs/sieve1.go /func.generate/ /^}/
+<pre><!--{{code "progs/sieve1.go" `/func.generate/` `/^}/`}}
-->func generate() chan int {
ch := make(chan int)
- go func(){
+ go func() {
for i := 2; ; i++ {
ch &lt;- i
}
@@ -1283,12 +1283,12 @@ after <code>generate</code> returns.
<p>
The same change can be made to <code>filter</code>:
<p>
-<pre><!-- progs/sieve1.go /func.filter/ /^}/
+<pre><!--{{code "progs/sieve1.go" `/func.filter/` `/^}/`}}
-->func filter(in chan int, prime int) chan int {
out := make(chan int)
go func() {
for {
- if i := &lt;-in; i % prime != 0 {
+ if i := &lt;-in; i%prime != 0 {
out &lt;- i
}
}
@@ -1300,7 +1300,7 @@ The same change can be made to <code>filter</code>:
The <code>sieve</code> function's main loop becomes simpler and clearer as a
result, and while we're at it let's turn it into a factory too:
<p>
-<pre><!-- progs/sieve1.go /func.sieve/ /^}/
+<pre><!--{{code "progs/sieve1.go" `/func.sieve/` `/^}/`}}
-->func sieve() chan int {
out := make(chan int)
go func() {
@@ -1317,7 +1317,7 @@ result, and while we're at it let's turn it into a factory too:
<p>
Now <code>main</code>'s interface to the prime sieve is a channel of primes:
<p>
-<pre><!-- progs/sieve1.go /func.main/ /^}/
+<pre><!--{{code "progs/sieve1.go" `/func.main/` `/^}/`}}
-->func main() {
primes := sieve()
for i := 0; i &lt; 100; i++ { // Print the first hundred primes.
@@ -1335,17 +1335,17 @@ A realistic client-server program is a lot of code, so here is a very simple sub
to illustrate the idea. It starts by defining a <code>request</code> type, which embeds a channel
that will be used for the reply.
<p>
-<pre><!-- progs/server.go /type.request/ /^}/
+<pre><!--{{code "progs/server.go" `/type.request/` `/^}/`}}
-->type request struct {
- a, b int
- replyc chan int
+ a, b int
+ replyc chan int
}
</pre>
<p>
The server will be trivial: it will do simple binary operations on integers. Here's the
code that invokes the operation and responds to the request:
<p>
-<pre><!-- progs/server.go /type.binOp/ /^}/
+<pre><!--{{code "progs/server.go" `/type.binOp/` `/^}/`}}
-->type binOp func(a, b int) int
func run(op binOp, req *request) {
@@ -1360,11 +1360,11 @@ returning a third.
The <code>server</code> routine loops forever, receiving requests and, to avoid blocking due to
a long-running operation, starting a goroutine to do the actual work.
<p>
-<pre><!-- progs/server.go /func.server/ /^}/
+<pre><!--{{code "progs/server.go" `/func.server/` `/^}/`}}
-->func server(op binOp, service chan *request) {
for {
req := &lt;-service
- go run(op, req) // don't wait for it
+ go run(op, req) // don&#39;t wait for it
}
}
</pre>
@@ -1372,7 +1372,7 @@ a long-running operation, starting a goroutine to do the actual work.
We construct a server in a familiar way, starting it and returning a channel
connected to it:
<p>
-<pre><!-- progs/server.go /func.startServer/ /^}/
+<pre><!--{{code "progs/server.go" `/func.startServer/` `/^}/`}}
-->func startServer(op binOp) chan *request {
req := make(chan *request)
go server(op, req)
@@ -1384,7 +1384,7 @@ Here's a simple test. It starts a server with an addition operator and sends ou
<code>N</code> requests without waiting for the replies. Only after all the requests are sent
does it check the results.
<p>
-<pre><!-- progs/server.go /func.main/ /^}/
+<pre><!--{{code "progs/server.go" `/func.main/` `/^}/`}}
-->func main() {
adder := startServer(func(a, b int) int { return a + b })
const N = 100
@@ -1396,8 +1396,8 @@ does it check the results.
req.replyc = make(chan int)
adder &lt;- req
}
- for i := N-1; i &gt;= 0; i-- { // doesn&#39;t matter what order
- if &lt;-reqs[i].replyc != N + 2*i {
+ for i := N - 1; i &gt;= 0; i-- { // doesn&#39;t matter what order
+ if &lt;-reqs[i].replyc != N+2*i {
fmt.Println(&#34;fail at&#34;, i)
}
}
@@ -1409,7 +1409,7 @@ One annoyance with this program is that it doesn't shut down the server cleanly;
there are a number of lingering goroutines blocked on communication. To solve this,
we can provide a second, <code>quit</code> channel to the server:
<p>
-<pre><!-- progs/server1.go /func.startServer/ /^}/
+<pre><!--{{code "progs/server1.go" `/func.startServer/` `/^}/`}}
-->func startServer(op binOp) (service chan *request, quit chan bool) {
service = make(chan *request)
quit = make(chan bool)
@@ -1420,12 +1420,12 @@ we can provide a second, <code>quit</code> channel to the server:
<p>
It passes the quit channel to the <code>server</code> function, which uses it like this:
<p>
-<pre><!-- progs/server1.go /func.server/ /^}/
+<pre><!--{{code "progs/server1.go" `/func.server/` `/^}/`}}
-->func server(op binOp, service chan *request, quit chan bool) {
for {
select {
case req := &lt;-service:
- go run(op, req) // don't wait for it
+ go run(op, req) // don&#39;t wait for it
case &lt;-quit:
return
}
@@ -1443,11 +1443,11 @@ returns, terminating its execution.
All that's left is to strobe the <code>quit</code> channel
at the end of main:
<p>
-<pre><!-- progs/server1.go /adder,.quit/
+<pre><!--{{code "progs/server1.go" `/adder,.quit/`}}
--> adder, quit := startServer(func(a, b int) int { return a + b })
</pre>
...
-<pre><!-- progs/server1.go /quit....true/
+<pre><!--{{code "progs/server1.go" `/quit....true/`}}
--> quit &lt;- true
</pre>
<p>