diff options
Diffstat (limited to 'doc/go_tutorial.html')
-rw-r--r-- | doc/go_tutorial.html | 176 |
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 "fmt" // Package implementing formatted I/O. +import fmt "fmt" // Package implementing formatted I/O. func main() { fmt.Printf("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n") @@ -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 ( "os" - "flag" // command line option parser + "flag" // command line option parser ) var omitNewline = flag.Bool("n", false, "don't print final newline") const ( - Space = " " + Space = " " Newline = "\n" ) 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 = "" for i := 0; i < flag.NArg(); i++ { if i > 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 < 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 := "hello" - if s[1] != 'e' { os.Exit(1) } + if s[1] != 'e' { + os.Exit(1) + } s = "good bye" var p *string = &s *p = "ciao" @@ -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 < 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 < 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, "/dev/stdin") Stdout = newFile(syscall.Stdout, "/dev/stdout") @@ -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'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("/does/not/exist") if f == nil { - fmt.Printf("can't open file; err=%s\n", err.String()) + fmt.Printf("can't open file; err=%s\n", 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("rot13", false, "rot13 the input") </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 < data.Len(); i++ { for j := i; j > 0 && 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] < 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] < 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 < 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 < 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<<64-1 +<pre><!--{{code "progs/print.go" 10 11}} +--> var u64 uint64 = 1<<64 - 1 fmt.Printf("%d %d\n", 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, " ", t, " ", a, "\n") 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 'ch'. func generate(ch chan int) { for i := 2; ; i++ { - ch <- i // Send 'i' to channel 'ch'. + ch <- i // Send 'i' to channel 'ch'. } } </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><-</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 'in' to channel 'out', +// removing those divisible by 'prime'. func filter(in, out chan int, prime int) { for { - i := <-in // Receive value of new variable 'i' from 'in'. - if i % prime != 0 { - out <- i // Send 'i' to channel 'out'. + i := <-in // Receive value of new variable 'i' from 'in'. + if i%prime != 0 { + out <- i // Send 'i' to channel 'out'. } } } @@ -1236,10 +1236,10 @@ result := <-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 < 100; i++ { // Print the first hundred primes. prime := <-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 <- 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 := <-in; i % prime != 0 { + if i := <-in; i%prime != 0 { out <- 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 < 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 := <-service - go run(op, req) // don't wait for it + go run(op, req) // don'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 <- req } - for i := N-1; i >= 0; i-- { // doesn't matter what order - if <-reqs[i].replyc != N + 2*i { + for i := N - 1; i >= 0; i-- { // doesn't matter what order + if <-reqs[i].replyc != N+2*i { fmt.Println("fail at", 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 := <-service: - go run(op, req) // don't wait for it + go run(op, req) // don't wait for it case <-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 <- true </pre> <p> |