| <!-- A Tutorial for the Go Programming Language --> |
| <!-- |
| DO NOT EDIT: created by |
| tmpltohtml go_tutorial.tmpl |
| --> |
| |
| |
| <h2>Introduction</h2> |
| <p> |
| This document is a tutorial introduction to the basics of the Go programming |
| language, intended for programmers familiar with C or C++. It is not a comprehensive |
| guide to the language; at the moment the document closest to that is the |
| <a href='/doc/go_spec.html'>language specification</a>. |
| After you've read this tutorial, you should look at |
| <a href='/doc/effective_go.html'>Effective Go</a>, |
| which digs deeper into how the language is used and |
| talks about the style and idioms of programming in Go. |
| An interactive introduction to Go is available, called |
| <a href='http://tour.golang.org/'>A Tour of Go</a>. |
| <p> |
| 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> |
| <h2>Hello, World</h2> |
| <p> |
| Let's start in the usual way: |
| <p> |
| <pre><!--{{code "progs/helloworld.go" `/package/` "$"}} |
| -->package main |
| |
| import fmt "fmt" // Package implementing formatted I/O. |
| |
| func main() { |
| fmt.Printf("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n") |
| }</pre> |
| <p> |
| Every Go source file declares, using a <code>package</code> statement, which package it's part of. |
| It may also import other packages to use their facilities. |
| This program imports the package <code>fmt</code> to gain access to |
| our old, now capitalized and package-qualified, friend, <code>fmt.Printf</code>. |
| <p> |
| Functions are introduced with the <code>func</code> keyword. |
| The <code>main</code> package's <code>main</code> function is where the program starts running (after |
| any initialization). |
| <p> |
| String constants can contain Unicode characters, encoded in UTF-8. |
| (In fact, Go source files are defined to be encoded in UTF-8.) |
| <p> |
| The comment convention is the same as in C++: |
| <p> |
| <pre> |
| /* ... */ |
| // ... |
| </pre> |
| <p> |
| Later we'll have much more to say about printing. |
| <p> |
| <h2>Semicolons</h2> |
| <p> |
| You might have noticed that our program has no semicolons. In Go |
| code, the only place you typically see semicolons is separating the |
| clauses of <code>for</code> loops and the like; they are not necessary after |
| every statement. |
| <p> |
| In fact, what happens is that the formal language uses semicolons, |
| much as in C or Java, but they are inserted automatically |
| at the end of every line that looks like the end of a statement. You |
| don't need to type them yourself. |
| <p> |
| For details about how this is done you can see the language |
| specification, but in practice all you need to know is that you |
| never need to put a semicolon at the end of a line. (You can put |
| them in if you want to write multiple statements per line.) As an |
| extra help, you can also leave out a semicolon immediately before |
| a closing brace. |
| <p> |
| This approach makes for clean-looking, semicolon-free code. The |
| one surprise is that it's important to put the opening |
| brace of a construct such as an <code>if</code> statement on the same line as |
| the <code>if</code>; if you don't, there are situations that may not compile |
| or may give the wrong result. The language forces the brace style |
| to some extent. |
| <p> |
| <h2>Compiling</h2> |
| <p> |
| Go is a compiled language. At the moment there are two compilers. |
| <code>Gccgo</code> is a Go compiler that uses the GCC back end. There is also a |
| suite of compilers with different (and odd) names for each architecture: |
| <code>6g</code> for the 64-bit x86, <code>8g</code> for the 32-bit x86, and more. These |
| compilers run significantly faster but generate less efficient code |
| than <code>gccgo</code>. At the time of writing (late 2009), they also have |
| a more robust run-time system although <code>gccgo</code> is catching up. |
| <p> |
| Here's how to compile and run our program. With <code>6g</code>, say, |
| <p> |
| <pre> |
| $ 6g helloworld.go # compile; object goes into helloworld.6 |
| $ 6l helloworld.6 # link; output goes into 6.out |
| $ ./6.out |
| Hello, world; or Καλημέρα κόσμε; or こんにちは 世界 |
| $ |
| </pre> |
| <p> |
| With <code>gccgo</code> it looks a little more traditional. |
| <p> |
| <pre> |
| $ gccgo helloworld.go |
| $ ./a.out |
| Hello, world; or Καλημέρα κόσμε; or こんにちは 世界 |
| $ |
| </pre> |
| <p> |
| <h2>Echo</h2> |
| <p> |
| Next up, here's a version of the Unix utility <code>echo(1)</code>: |
| <p> |
| <pre><!--{{code "progs/echo.go" `/package/` "$"}} |
| -->package main |
| |
| import ( |
| "flag" // command line option parser |
| "os" |
| ) |
| |
| var omitNewline = flag.Bool("n", false, "don't print final newline") |
| |
| const ( |
| Space = " " |
| Newline = "\n" |
| ) |
| |
| func main() { |
| flag.Parse() // Scans the arg list and sets up flags |
| var s string = "" |
| for i := 0; i < flag.NArg(); i++ { |
| if i > 0 { |
| s += Space |
| } |
| s += flag.Arg(i) |
| } |
| if !*omitNewline { |
| s += Newline |
| } |
| os.Stdout.WriteString(s) |
| }</pre> |
| <p> |
| This program is small but it's doing a number of new things. In the last example, |
| we saw <code>func</code> introduce a function. The keywords <code>var</code>, <code>const</code>, and <code>type</code> |
| (not used yet) also introduce declarations, as does <code>import</code>. |
| Notice that we can group declarations of the same sort into |
| parenthesized lists, one item per line, as in the <code>import</code> and <code>const</code> clauses here. |
| But it's not necessary to do so; we could have said |
| <p> |
| <pre> |
| const Space = " " |
| const Newline = "\n" |
| </pre> |
| <p> |
| This program imports the <code>"os"</code> package to access its <code>Stdout</code> variable, of type |
| <code>*os.File</code>. The <code>import</code> statement is actually a declaration: in its general form, |
| as used in our ``hello world'' program, |
| it names the identifier (<code>fmt</code>) |
| that will be used to access members of the package imported from the file (<code>"fmt"</code>), |
| found in the current directory or in a standard location. |
| In this program, though, we've dropped the explicit name from the imports; by default, |
| packages are imported using the name defined by the imported package, |
| which by convention is of course the file name itself. Our ``hello world'' program |
| could have said just <code>import "fmt"</code>. |
| <p> |
| You can specify your |
| own import names if you want but it's only necessary if you need to resolve |
| a naming conflict. |
| <p> |
| Given <code>os.Stdout</code> we can use its <code>WriteString</code> method to print the string. |
| <p> |
| 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 (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> |
| <pre> |
| var s string = "" |
| </pre> |
| <p> |
| This is the <code>var</code> keyword, followed by the name of the variable, followed by |
| its type, followed by an equals sign and an initial value for the variable. |
| <p> |
| Go tries to be terse, and this declaration could be shortened. Since the |
| string constant is of type string, we don't have to tell the compiler that. |
| We could write |
| <p> |
| <pre> |
| var s = "" |
| </pre> |
| <p> |
| or we could go even shorter and write the idiom |
| <p> |
| <pre> |
| s := "" |
| </pre> |
| <p> |
| 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><!--{{code "progs/echo.go" `/for/`}} |
| --> for i := 0; i < flag.NArg(); i++ {</pre> |
| <p> |
| The <code>flag</code> package has parsed the arguments and left the non-flag arguments |
| in a list that can be iterated over in the obvious way. |
| <p> |
| The Go <code>for</code> statement differs from that of C in a number of ways. First, |
| it's the only looping construct; there is no <code>while</code> or <code>do</code>. Second, |
| there are no parentheses on the clause, but the braces on the body |
| are mandatory. The same applies to the <code>if</code> and <code>switch</code> statements. |
| Later examples will show some other ways <code>for</code> can be written. |
| <p> |
| The body of the loop builds up the string <code>s</code> by appending (using <code>+=</code>) |
| the arguments and separating spaces. After the loop, if the <code>-n</code> flag is not |
| set, the program appends a newline. Finally, it writes the result. |
| <p> |
| Notice that <code>main.main</code> is a niladic function with no return type. |
| It's defined that way. Falling off the end of <code>main.main</code> means |
| ''success''; if you want to signal an erroneous return, call |
| <p> |
| <pre> |
| os.Exit(1) |
| </pre> |
| <p> |
| The <code>os</code> package contains other essentials for getting |
| started; for instance, <code>os.Args</code> is a slice used by the |
| <code>flag</code> package to access the command-line arguments. |
| <p> |
| <h2>An Interlude about Types</h2> |
| <p> |
| Go has some familiar types such as <code>int</code> and <code>uint</code> (unsigned <code>int</code>), which represent |
| values of the ''appropriate'' size for the machine. It also defines |
| explicitly-sized types such as <code>int8</code>, <code>float64</code>, and so on, plus |
| unsigned integer types such as <code>uint</code>, <code>uint32</code>, etc. |
| These are distinct types; even if <code>int</code> and <code>int32</code> are both 32 bits in size, |
| they are not the same type. There is also a <code>byte</code> synonym for |
| <code>uint8</code>, which is the element type for strings. |
| <p> |
| Floating-point types are always sized: <code>float32</code> and <code>float64</code>, |
| plus <code>complex64</code> (two <code>float32s</code>) and <code>complex128</code> |
| (two <code>float64s</code>). Complex numbers are outside the |
| scope of this tutorial. |
| <p> |
| Speaking of <code>string</code>, that's a built-in type as well. Strings are |
| <i>immutable values</i>—they are not just arrays of <code>byte</code> values. |
| 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><!--{{code "progs/strings.go" `/hello/` `/ciao/`}} |
| --> s := "hello" |
| if s[1] != 'e' { |
| os.Exit(1) |
| } |
| s = "good bye" |
| var p *string = &s |
| *p = "ciao"</pre> |
| <p> |
| However the following statements are illegal because they would modify |
| a <code>string</code> value: |
| <p> |
| <pre> |
| s[0] = 'x' |
| (*p)[1] = 'y' |
| </pre> |
| <p> |
| In C++ terms, Go strings are a bit like <code>const strings</code>, while pointers |
| to strings are analogous to <code>const string</code> references. |
| <p> |
| Yes, there are pointers. However, Go simplifies their use a little; |
| read on. |
| <p> |
| Arrays are declared like this: |
| <p> |
| <pre> |
| var arrayOfInt [10]int |
| </pre> |
| <p> |
| Arrays, like strings, are values, but they are mutable. This differs |
| from C, in which <code>arrayOfInt</code> would be usable as a pointer to <code>int</code>. |
| In Go, since arrays are values, it's meaningful (and useful) to talk |
| about pointers to arrays. |
| <p> |
| The size of the array is part of its type; however, one can declare |
| a <i>slice</i> variable to hold a reference to any array, of any size, |
| with the same element type. |
| A <i>slice |
| expression</i> has the form <code>a[low : high]</code>, representing |
| the internal array indexed from <code>low</code> through <code>high-1</code>; the resulting |
| slice is indexed from <code>0</code> through <code>high-low-1</code>. |
| In short, slices look a lot like arrays but with |
| no explicit size (<code>[]</code> vs. <code>[10]</code>) and they reference a segment of |
| an underlying, usually anonymous, regular array. Multiple slices |
| can share data if they represent pieces of the same array; |
| multiple arrays can never share data. |
| <p> |
| Slices are much more common in Go programs than |
| regular arrays; they're more flexible, have reference semantics, |
| and are efficient. What they lack is the precise control of storage |
| layout of a regular array; if you want to have a hundred elements |
| of an array stored within your structure, you should use a regular |
| array. To create one, use a compound value <i>constructor</i>—an |
| expression formed |
| from a type followed by a brace-bounded expression like this: |
| <p> |
| <pre> |
| [3]int{1,2,3} |
| </pre> |
| <p> |
| In this case the constructor builds an array of 3 <code>ints</code>. |
| <p> |
| When passing an array to a function, you almost always want |
| to declare the formal parameter to be a slice. When you call |
| the function, slice the array to create |
| (efficiently) a slice reference and pass that. |
| By default, the lower and upper bounds of a slice match the |
| ends of the existing object, so the concise notation <code>[:]</code> |
| will slice the whole array. |
| <p> |
| Using slices one can write this function (from <code>sum.go</code>): |
| <p> |
| <pre><!--{{code "progs/sum.go" `/sum/` `/^}/`}} |
| -->func sum(a []int) int { // returns an int |
| s := 0 |
| for i := 0; i < len(a); i++ { |
| s += a[i] |
| } |
| return s |
| }</pre> |
| <p> |
| Note how the return type (<code>int</code>) is defined for <code>sum</code> by stating it |
| after the parameter list. |
| <p> |
| To call the function, we slice the array. This code (we'll show |
| a simpler way in a moment) constructs |
| an array and slices it: |
| <p> |
| <pre> |
| x := [3]int{1,2,3} |
| s := sum(x[:]) |
| </pre> |
| <p> |
| If you are creating a regular array but want the compiler to count the |
| elements for you, use <code>...</code> as the array size: |
| <p> |
| <pre> |
| x := [...]int{1,2,3} |
| s := sum(x[:]) |
| </pre> |
| <p> |
| That's fussier than necessary, though. |
| In practice, unless you're meticulous about storage layout within a |
| data structure, a slice itself—using empty brackets with no size—is all you need: |
| <p> |
| <pre> |
| s := sum([]int{1,2,3}) |
| </pre> |
| <p> |
| There are also maps, which you can initialize like this: |
| <p> |
| <pre> |
| m := map[string]int{"one":1 , "two":2} |
| </pre> |
| <p> |
| The built-in function <code>len</code>, which returns number of elements, |
| makes its first appearance in <code>sum</code>. It works on strings, arrays, |
| slices, maps, and channels. |
| <p> |
| By the way, another thing that works on strings, arrays, slices, maps |
| and channels is the <code>range</code> clause on <code>for</code> loops. Instead of writing |
| <p> |
| <pre> |
| for i := 0; i < len(a); i++ { ... } |
| </pre> |
| <p> |
| to loop over the elements of a slice (or map or ...) , we could write |
| <p> |
| <pre> |
| for i, v := range a { ... } |
| </pre> |
| <p> |
| This assigns <code>i</code> to the index and <code>v</code> to the value of the successive |
| elements of the target of the range. See |
| <a href='/doc/effective_go.html'>Effective Go</a> |
| for more examples of its use. |
| <p> |
| <p> |
| <h2>An Interlude about Allocation</h2> |
| <p> |
| Most types in Go are values. If you have an <code>int</code> or a <code>struct</code> |
| or an array, assignment |
| copies the contents of the object. |
| To allocate a new variable, use the built-in function <code>new</code>, which |
| returns a pointer to the allocated storage. |
| <p> |
| <pre> |
| type T struct { a, b int } |
| var t *T = new(T) |
| </pre> |
| <p> |
| or the more idiomatic |
| <p> |
| <pre> |
| t := new(T) |
| </pre> |
| <p> |
| Some types—maps, slices, and channels (see below)—have reference semantics. |
| If you're holding a slice or a map and you modify its contents, other variables |
| referencing the same underlying data will see the modification. For these three |
| types you want to use the built-in function <code>make</code>: |
| <p> |
| <pre> |
| m := make(map[string]int) |
| </pre> |
| <p> |
| This statement initializes a new map ready to store entries. |
| If you just declare the map, as in |
| <p> |
| <pre> |
| var m map[string]int |
| </pre> |
| <p> |
| it creates a <code>nil</code> reference that cannot hold anything. To use the map, |
| you must first initialize the reference using <code>make</code> or by assignment from an |
| existing map. |
| <p> |
| Note that <code>new(T)</code> returns type <code>*T</code> while <code>make(T)</code> returns type |
| <code>T</code>. If you (mistakenly) allocate a reference object with <code>new</code> rather than <code>make</code>, |
| you receive a pointer to a nil reference, equivalent to |
| declaring an uninitialized variable and taking its address. |
| <p> |
| <h2>An Interlude about Constants</h2> |
| <p> |
| Although integers come in lots of sizes in Go, integer constants do not. |
| There are no constants like <code>0LL</code> or <code>0x0UL</code>. Instead, integer |
| constants are evaluated as large-precision values that |
| can overflow only when they are assigned to an integer variable with |
| too little precision to represent the value. |
| <p> |
| <pre> |
| const hardEight = (1 << 100) >> 97 // legal |
| </pre> |
| <p> |
| There are nuances that deserve redirection to the legalese of the |
| language specification but here are some illustrative examples: |
| <p> |
| <pre> |
| var a uint64 = 0 // a has type uint64, value 0 |
| a := uint64(0) // equivalent; uses a "conversion" |
| i := 0x1234 // i gets default type: int |
| var j int = 1e6 // legal - 1000000 is representable in an int |
| x := 1.5 // a float64, the default type for floating constants |
| i3div2 := 3/2 // integer division - result is 1 |
| f3div2 := 3./2. // floating-point division - result is 1.5 |
| </pre> |
| <p> |
| Conversions only work for simple cases such as converting <code>ints</code> of one |
| sign or size to another and between integers and floating-point numbers, |
| plus a couple of other instances outside the scope of a tutorial. |
| There are no automatic numeric conversions of any kind in Go, |
| other than that of making constants have concrete size and type when |
| assigned to a variable. |
| <p> |
| <h2>An I/O Package</h2> |
| <p> |
| Next we'll look at a simple package for doing Unix file I/O with an |
| open/close/read/write interface. |
| Here's the start of <code>file.go</code>: |
| <p> |
| <pre><!--{{code "progs/file.go" `/package/` `/^}/`}} |
| -->package file |
| |
| import ( |
| "os" |
| "syscall" |
| ) |
| |
| type File struct { |
| fd int // file descriptor number |
| name string // file name at Open time |
| }</pre> |
| <p> |
| The first few lines declare the name of the |
| package—<code>file</code>—and then import two packages. The <code>os</code> |
| package hides the differences |
| between various operating systems to give a consistent view of files and |
| so on; here we're going to use its error handling utilities |
| and reproduce the rudiments of its file I/O. |
| <p> |
| The other item is the low-level, external <code>syscall</code> package, which provides |
| a primitive interface to the underlying operating system's calls. |
| The <code>syscall</code> package is very system-dependent, and the way it's |
| used here works only on Unix-like systems, |
| but the general ideas explored here apply broadly. |
| (A Windows version is available in |
| <a href="progs/file_windows.go"><code>file_windows.go</code></a>.) |
| <p> |
| Next is a type definition: the <code>type</code> keyword introduces a type declaration, |
| in this case a data structure called <code>File</code>. |
| To make things a little more interesting, our <code>File</code> includes the name of the file |
| that the file descriptor refers to. |
| <p> |
| Because <code>File</code> starts with a capital letter, the type is available outside the package, |
| that is, by users of the package. In Go the rule about visibility of information is |
| simple: if a name (of a top-level type, function, method, constant or variable, or of |
| a structure field or method) is capitalized, users of the package may see it. Otherwise, the |
| name and hence the thing being named is visible only inside the package in which |
| it is declared. This is more than a convention; the rule is enforced by the compiler. |
| In Go, the term for publicly visible names is ''exported''. |
| <p> |
| In the case of <code>File</code>, all its fields are lower case and so invisible to users, but we |
| will soon give it some exported, upper-case methods. |
| <p> |
| First, though, here is a factory to create a <code>File</code>: |
| <p> |
| <pre><!--{{code "progs/file.go" `/newFile/` `/^}/`}} |
| -->func newFile(fd int, name string) *File { |
| if fd < 0 { |
| return nil |
| } |
| return &File{fd, name} |
| }</pre> |
| <p> |
| This returns a pointer to a new <code>File</code> structure with the file descriptor and name |
| filled in. This code uses Go's notion of a ''composite literal'', analogous to |
| the ones used to build maps and arrays, to construct a new heap-allocated |
| object. We could write |
| <p> |
| <pre> |
| n := new(File) |
| n.fd = fd |
| n.name = name |
| 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 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><!--{{code "progs/file.go" `/var/` `/^\)/`}} |
| -->var ( |
| Stdin = newFile(syscall.Stdin, "/dev/stdin") |
| Stdout = newFile(syscall.Stdout, "/dev/stdout") |
| Stderr = newFile(syscall.Stderr, "/dev/stderr") |
| )</pre> |
| <p> |
| 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><!--{{code "progs/file.go" `/func.OpenFile/` `/^}/`}} |
| -->func OpenFile(name string, mode int, perm uint32) (file *File, err error) { |
| r, err := syscall.Open(name, mode, perm) |
| return newFile(r, name), err |
| }</pre> |
| <p> |
| There are a number of new things in these few lines. First, <code>OpenFile</code> returns |
| multiple values, a <code>File</code> and an error (more about errors in a moment). |
| We declare the |
| 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 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, <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> |
| About those errors: The Go language includes a general notion of an error: |
| a pre-defined type <code>error</code> with properties (described below) |
| that make it a good basis for representing and handling errors. |
| It's a good idea to use its facility in your own interfaces, as we do here, for |
| consistent error handling throughout Go code. In <code>Open</code> we use a |
| conversion to translate Unix's integer <code>errno</code> value into the integer type |
| <code>os.Errno</code>, which is an implementation of <code>error</code> |
| <p> |
| Why <code>OpenFile</code> and not <code>Open</code>? To mimic Go's <code>os</code> package, which |
| our exercise is emulating. The <code>os</code> package takes the opportunity |
| to make the two commonest cases - open for read and create for |
| write - the simplest, just <code>Open</code> and <code>Create</code>. <code>OpenFile</code> is the |
| general case, analogous to the Unix system call <code>Open</code>. Here is |
| the implementation of our <code>Open</code> and <code>Create</code>; they're trivial |
| wrappers that eliminate common errors by capturing |
| the tricky standard arguments to open and, especially, to create a file: |
| <p> |
| <pre><!--{{code "progs/file.go" `/^const/` `/^}/`}} |
| -->const ( |
| O_RDONLY = syscall.O_RDONLY |
| O_RDWR = syscall.O_RDWR |
| O_CREATE = syscall.O_CREAT |
| O_TRUNC = syscall.O_TRUNC |
| ) |
| |
| func Open(name string) (file *File, err error) { |
| return OpenFile(name, O_RDONLY, 0) |
| }</pre> |
| <p> |
| <pre><!--{{code "progs/file.go" `/func.Create/` `/^}/`}} |
| -->func Create(name string) (file *File, err error) { |
| return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666) |
| }</pre> |
| <p> |
| Back to our main story. |
| Now that we can build <code>Files</code>, we can write methods for them. To declare |
| a method of a type, we define a function to have an explicit receiver |
| 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><!--{{code "progs/file.go" `/Close/` "$"}} |
| -->func (file *File) Close() error { |
| if file == nil { |
| return os.EINVAL |
| } |
| err := syscall.Close(file.fd) |
| file.fd = -1 // so it can't be closed again |
| return err |
| } |
| |
| func (file *File) Read(b []byte) (ret int, err error) { |
| if file == nil { |
| return -1, os.EINVAL |
| } |
| r, err := syscall.Read(file.fd, b) |
| return int(r), err |
| } |
| |
| func (file *File) Write(b []byte) (ret int, err error) { |
| if file == nil { |
| return -1, os.EINVAL |
| } |
| r, err := syscall.Write(file.fd, b) |
| return int(r), err |
| } |
| |
| func (file *File) String() string { |
| return file.name |
| }</pre> |
| <p> |
| There is no implicit <code>this</code> and the receiver variable must be used to access |
| members of the structure. Methods are not declared within |
| the <code>struct</code> declaration itself. The <code>struct</code> declaration defines only data members. |
| In fact, methods can be created for almost any type you name, such as an integer or |
| array, not just for <code>structs</code>. We'll see an example with arrays later. |
| <p> |
| The <code>String</code> method is so called because of a printing convention we'll |
| describe later. |
| <p> |
| The methods use the public variable <code>os.EINVAL</code> to return the (<code>error</code> |
| version of the) Unix error code <code>EINVAL</code>. The <code>os</code> library defines a standard |
| set of such error values. |
| <p> |
| We can now use our new package: |
| <p> |
| <pre><!--{{code "progs/helloworld3.go" `/package/` "$"}} |
| -->package main |
| |
| import ( |
| "./file" |
| "fmt" |
| "os" |
| ) |
| |
| func main() { |
| hello := []byte("hello, world\n") |
| file.Stdout.Write(hello) |
| f, err := file.Open("/does/not/exist") |
| if f == nil { |
| fmt.Printf("can't open file; err=%s\n", err.Error()) |
| os.Exit(1) |
| } |
| }</pre> |
| <p> |
| The ''<code>./</code>'' in the import of ''<code>./file</code>'' tells the compiler |
| to use our own package rather than |
| something from the directory of installed packages. |
| (Also, ''<code>file.go</code>'' must be compiled before we can import the |
| package.) |
| <p> |
| Now we can compile and run the program. On Unix, this would be the result: |
| <p> |
| <pre> |
| $ 6g file.go # compile file package |
| $ 6g helloworld3.go # compile main package |
| $ 6l -o helloworld3 helloworld3.6 # link - no need to mention "file" |
| $ ./helloworld3 |
| hello, world |
| can't open file; err=No such file or directory |
| $ |
| </pre> |
| <p> |
| <h2>Rotting cats</h2> |
| <p> |
| 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><!--{{code "progs/cat.go" `/package/` "$"}} |
| -->package main |
| |
| import ( |
| "./file" |
| "flag" |
| "fmt" |
| "os" |
| ) |
| |
| func cat(f *file.File) { |
| const NBUF = 512 |
| var buf [NBUF]byte |
| for { |
| switch nr, er := f.Read(buf[:]); true { |
| case nr < 0: |
| fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", f, er) |
| os.Exit(1) |
| case nr == 0: // EOF |
| return |
| case nr > 0: |
| if nw, ew := file.Stdout.Write(buf[0:nr]); nw != nr { |
| fmt.Fprintf(os.Stderr, "cat: error writing from %s: %s\n", f, ew) |
| os.Exit(1) |
| } |
| } |
| } |
| } |
| |
| func main() { |
| flag.Parse() // Scans the arg list and sets up flags |
| if flag.NArg() == 0 { |
| cat(file.Stdin) |
| } |
| for i := 0; i < flag.NArg(); i++ { |
| f, err := file.Open(flag.Arg(i)) |
| if f == nil { |
| fmt.Fprintf(os.Stderr, "cat: can't open %s: error %s\n", flag.Arg(i), err) |
| os.Exit(1) |
| } |
| cat(f) |
| f.Close() |
| } |
| }</pre> |
| <p> |
| By now this should be easy to follow, but the <code>switch</code> statement introduces some |
| new features. Like a <code>for</code> loop, an <code>if</code> or <code>switch</code> can include an |
| initialization statement. The <code>switch</code> statement in <code>cat</code> uses one to create variables |
| <code>nr</code> and <code>er</code> to hold the return values from the call to <code>f.Read</code>. (The <code>if</code> a few lines later |
| has the same idea.) The <code>switch</code> statement is general: it evaluates the cases |
| from top to bottom looking for the first case that matches the value; the |
| case expressions don't need to be constants or even integers, as long as |
| they all have the same type. |
| <p> |
| Since the <code>switch</code> value is just <code>true</code>, we could leave it off—as is also |
| the situation |
| in a <code>for</code> statement, a missing value means <code>true</code>. In fact, such a <code>switch</code> |
| is a form of <code>if-else</code> chain. While we're here, it should be mentioned that in |
| <code>switch</code> statements each <code>case</code> has an implicit <code>break</code>. |
| <p> |
| The argument to <code>file.Stdout.Write</code> is created by slicing the array <code>buf</code>. |
| Slices provide the standard Go way to handle I/O buffers. |
| <p> |
| Now let's make a variant of <code>cat</code> that optionally does <code>rot13</code> on its input. |
| It's easy to do by just processing the bytes, but instead we will exploit |
| Go's notion of an <i>interface</i>. |
| <p> |
| The <code>cat</code> subroutine uses only two methods of <code>f</code>: <code>Read</code> and <code>String</code>, |
| 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><!--{{code "progs/cat_rot13.go" `/type.reader/` `/^}/`}} |
| -->type reader interface { |
| Read(b []byte) (ret int, err error) |
| String() string |
| }</pre> |
| <p> |
| Any type that has the two methods of <code>reader</code>—regardless of whatever |
| other methods the type may also have—is said to <i>implement</i> the |
| interface. Since <code>file.File</code> implements these methods, it implements the |
| <code>reader</code> interface. We could tweak the <code>cat</code> subroutine to accept a <code>reader</code> |
| instead of a <code>*file.File</code> and it would work just fine, but let's embellish a little |
| first by writing a second type that implements <code>reader</code>, one that wraps an |
| existing <code>reader</code> and does <code>rot13</code> on the data. To do this, we just define |
| the type and implement the methods and with no other bookkeeping, |
| we have a second implementation of the <code>reader</code> interface. |
| <p> |
| <pre><!--{{code "progs/cat_rot13.go" `/type.rotate13/` `/end.of.rotate13/`}} |
| -->type rotate13 struct { |
| source reader |
| } |
| |
| func newRotate13(source reader) *rotate13 { |
| return &rotate13{source} |
| } |
| |
| func (r13 *rotate13) Read(b []byte) (ret int, err error) { |
| r, e := r13.source.Read(b) |
| for i := 0; i < r; i++ { |
| b[i] = rot13(b[i]) |
| } |
| return r, e |
| } |
| |
| func (r13 *rotate13) String() string { |
| return r13.source.String() |
| }</pre> |
| <p> |
| (The <code>rot13</code> function called in <code>Read</code> is trivial and not worth reproducing here.) |
| <p> |
| To use the new feature, we define a flag: |
| <p> |
| <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><!--{{code "progs/cat_rot13.go" `/func.cat/` `/^}/`}} |
| -->func cat(r reader) { |
| const NBUF = 512 |
| var buf [NBUF]byte |
| |
| if *rot13Flag { |
| r = newRotate13(r) |
| } |
| for { |
| switch nr, er := r.Read(buf[:]); { |
| case nr < 0: |
| fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", r, er) |
| os.Exit(1) |
| case nr == 0: // EOF |
| return |
| case nr > 0: |
| nw, ew := file.Stdout.Write(buf[0:nr]) |
| if nw != nr { |
| fmt.Fprintf(os.Stderr, "cat: error writing from %s: %s\n", r, ew) |
| os.Exit(1) |
| } |
| } |
| } |
| }</pre> |
| <p> |
| (We could also do the wrapping in <code>main</code> and leave <code>cat</code> mostly alone, except |
| for changing the type of the argument; consider that an exercise.) |
| The <code>if</code> at the top of <code>cat</code> sets it all up: If the <code>rot13</code> flag is true, wrap the <code>reader</code> |
| we received into a <code>rotate13</code> and proceed. Note that the interface variables |
| are values, not pointers: the argument is of type <code>reader</code>, not <code>*reader</code>, |
| even though under the covers it holds a pointer to a <code>struct</code>. |
| <p> |
| Here it is in action: |
| <p> |
| <pre> |
| $ echo abcdefghijklmnopqrstuvwxyz | ./cat |
| abcdefghijklmnopqrstuvwxyz |
| $ echo abcdefghijklmnopqrstuvwxyz | ./cat --rot13 |
| nopqrstuvwxyzabcdefghijklm |
| $ |
| </pre> |
| <p> |
| Fans of dependency injection may take cheer from how easily interfaces |
| allow us to substitute the implementation of a file descriptor. |
| <p> |
| Interfaces are a distinctive feature of Go. An interface is implemented by a |
| type if the type implements all the methods declared in the interface. |
| This means |
| that a type may implement an arbitrary number of different interfaces. |
| There is no type hierarchy; things can be much more <i>ad hoc</i>, |
| as we saw with <code>rot13</code>. The type <code>file.File</code> implements <code>reader</code>; it could also |
| implement a <code>writer</code>, or any other interface built from its methods that |
| fits the current situation. Consider the <i>empty interface</i> |
| <p> |
| <pre> |
| type Empty interface {} |
| </pre> |
| <p> |
| <i>Every</i> type implements the empty interface, which makes it |
| useful for things like containers. |
| <p> |
| <h2>Sorting</h2> |
| <p> |
| Interfaces provide a simple form of polymorphism. They completely |
| separate the definition of what an object does from how it does it, allowing |
| distinct implementations to be represented at different times by the |
| same interface variable. |
| <p> |
| As an example, consider this simple sort algorithm taken from <code>progs/sort.go</code>: |
| <p> |
| <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-- { |
| data.Swap(j, j-1) |
| } |
| } |
| }</pre> |
| <p> |
| The code needs only three methods, which we wrap into sort's <code>Interface</code>: |
| <p> |
| <pre><!--{{code "progs/sort.go" `/interface/` `/^}/`}} |
| -->type Interface interface { |
| Len() int |
| Less(i, j int) bool |
| Swap(i, j int) |
| }</pre> |
| <p> |
| We can apply <code>Sort</code> to any type that implements <code>Len</code>, <code>Less</code>, and <code>Swap</code>. |
| 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><!--{{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] }</pre> |
| <p> |
| Here we see methods defined for non-<code>struct</code> types. You can define methods |
| for any type you define and name in your package. |
| <p> |
| 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><!--{{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) |
| sort.Sort(a) |
| if !sort.IsSorted(a) { |
| panic("fail") |
| } |
| }</pre> |
| <p> |
| 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><!--{{code "progs/sortmain.go" `/type.day/` `/Swap/`}} |
| -->type day struct { |
| 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] }</pre> |
| <p> |
| <p> |
| <h2>Printing</h2> |
| <p> |
| The examples of formatted printing so far have been modest. In this section |
| we'll talk about how formatted I/O can be done well in Go. |
| <p> |
| We've seen simple uses of the package <code>fmt</code>, which |
| implements <code>Printf</code>, <code>Fprintf</code>, and so on. |
| Within the <code>fmt</code> package, <code>Printf</code> is declared with this signature: |
| <p> |
| <pre> |
| Printf(format string, v ...interface{}) (n int, errno error) |
| </pre> |
| <p> |
| The token <code>...</code> introduces a variable-length argument list that in C would |
| be handled using the <code>stdarg.h</code> macros. |
| In Go, variadic functions are passed a slice of the arguments of the |
| specified type. In <code>Printf</code>'s case, the declaration says <code>...interface{}</code> |
| so the actual type is a slice of empty interface values, <code>[]interface{}</code>. |
| <code>Printf</code> can examine the arguments by iterating over the slice |
| and, for each element, using a type switch or the reflection library |
| to interpret the value. |
| It's off topic here but such run-time type analysis |
| helps explain some of the nice properties of Go's <code>Printf</code>, |
| due to the ability of <code>Printf</code> to discover the type of its arguments |
| dynamically. |
| <p> |
| For example, in C each format must correspond to the type of its |
| 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><!--{{code "progs/print.go" 10 11}} |
| --> var u64 uint64 = 1<<64 - 1 |
| fmt.Printf("%d %d\n", u64, int64(u64))</pre> |
| <p> |
| prints |
| <p> |
| <pre> |
| 18446744073709551615 -1 |
| </pre> |
| <p> |
| 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><!--{{code "progs/print.go" 14 20}} |
| --> type T struct { |
| a int |
| b string |
| } |
| t := T{77, "Sunset Strip"} |
| a := []int{1, 2, 3, 4} |
| fmt.Printf("%v %v %v\n", u64, t, a)</pre> |
| <p> |
| is |
| <p> |
| <pre> |
| 18446744073709551615 {77 Sunset Strip} [1 2 3 4] |
| </pre> |
| <p> |
| You can drop the formatting altogether if you use <code>Print</code> or <code>Println</code> |
| instead of <code>Printf</code>. Those routines do fully automatic formatting. |
| The <code>Print</code> function just prints its elements out using the equivalent |
| 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><!--{{code "progs/print.go" 21 22}} |
| --> fmt.Print(u64, " ", t, " ", a, "\n") |
| fmt.Println(u64, t, a)</pre> |
| <p> |
| If you have your own type you'd like <code>Printf</code> or <code>Print</code> to format, |
| just give it a <code>String</code> method that returns a string. The print |
| 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><!--{{code "progs/print_string.go" 9 "$"}} |
| -->type testType struct { |
| a int |
| b string |
| } |
| |
| func (t *testType) String() string { |
| return fmt.Sprint(t.a) + " " + t.b |
| } |
| |
| func main() { |
| t := &testType{77, "Sunset Strip"} |
| fmt.Println(t) |
| }</pre> |
| <p> |
| Since <code>*testType</code> has a <code>String</code> method, the |
| default formatter for that type will use it and produce the output |
| <p> |
| <pre> |
| 77 Sunset Strip |
| </pre> |
| <p> |
| Observe that the <code>String</code> method calls <code>Sprint</code> (the obvious Go |
| variant that returns a string) to do its formatting; special formatters |
| can use the <code>fmt</code> library recursively. |
| <p> |
| Another feature of <code>Printf</code> is that the format <code>%T</code> will print a string |
| representation of the type of a value, which can be handy when debugging |
| polymorphic code. |
| <p> |
| It's possible to write full custom print formats with flags and precisions |
| and such, but that's getting a little off the main thread so we'll leave it |
| as an exploration exercise. |
| <p> |
| You might ask, though, how <code>Printf</code> can tell whether a type implements |
| the <code>String</code> method. Actually what it does is ask if the value can |
| be converted to an interface variable that implements the method. |
| Schematically, given a value <code>v</code>, it does this: |
| <p> |
| <p> |
| <pre> |
| type Stringer interface { |
| String() string |
| } |
| </pre> |
| <p> |
| <pre> |
| s, ok := v.(Stringer) // Test whether v implements "String()" |
| if ok { |
| result = s.String() |
| } else { |
| result = defaultOutput(v) |
| } |
| </pre> |
| <p> |
| The code uses a ``type assertion'' (<code>v.(Stringer)</code>) to test if the value stored in |
| <code>v</code> satisfies the <code>Stringer</code> interface; if it does, <code>s</code> |
| will become an interface variable implementing the method and <code>ok</code> will |
| be <code>true</code>. We then use the interface variable to call the method. |
| (The ''comma, ok'' pattern is a Go idiom used to test the success of |
| operations such as type conversion, map update, communications, and so on, |
| although this is the only appearance in this tutorial.) |
| If the value does not satisfy the interface, <code>ok</code> will be false. |
| <p> |
| In this snippet the name <code>Stringer</code> follows the convention that we add ''[e]r'' |
| to interfaces describing simple method sets like this. |
| <p> |
| A related interface is that defined by the <code>error</code> builtin type, which is just |
| <p> |
| <pre> |
| type error interface { |
| Error() string |
| } |
| </pre> |
| <p> |
| Other than the method name (<code>Error</code> vs. <code>String</code>), this looks like |
| a <code>Stringer</code>; the different name guarantees that types that implement <code>Stringer</code> |
| don't accidentally satisfy the <code>error</code> interface. |
| Naturally, <code>Printf</code> and its relatives recognize the <code>error</code> interface, |
| just as they do <code>Stringer</code>, |
| so it's trivial to print an error as a string. |
| <p> |
| One last wrinkle. To complete the suite, besides <code>Printf</code> etc. and <code>Sprintf</code> |
| etc., there are also <code>Fprintf</code> etc. Unlike in C, <code>Fprintf</code>'s first argument is |
| not a file. Instead, it is a variable of type <code>io.Writer</code>, which is an |
| interface type defined in the <code>io</code> library: |
| <p> |
| <pre> |
| type Writer interface { |
| Write(p []byte) (n int, err error) |
| } |
| </pre> |
| <p> |
| (This interface is another conventional name, this time for <code>Write</code>; there are also |
| <code>io.Reader</code>, <code>io.ReadWriter</code>, and so on.) |
| Thus you can call <code>Fprintf</code> on any type that implements a standard <code>Write</code> |
| method, not just files but also network channels, buffers, whatever |
| you want. |
| <p> |
| <h2>Prime numbers</h2> |
| <p> |
| Now we come to processes and communication—concurrent programming. |
| It's a big subject so to be brief we assume some familiarity with the topic. |
| <p> |
| A classic program in the style is a prime sieve. |
| (The sieve of Eratosthenes is computationally more efficient than |
| the algorithm presented here, but we are more interested in concurrency than |
| algorithmics at the moment.) |
| It works by taking a stream of all the natural numbers and introducing |
| a sequence of filters, one for each prime, to winnow the multiples of |
| that prime. At each step we have a sequence of filters of the primes |
| so far, and the next number to pop out is the next prime, which triggers |
| the creation of the next filter in the chain. |
| <p> |
| Here's a flow diagram; each box represents a filter element whose |
| creation is triggered by the first number that flowed from the |
| elements before it. |
| <p> |
| <br> |
| <p> |
| <img src='sieve.gif'> |
| <p> |
| <br> |
| <p> |
| To create a stream of integers, we use a Go <i>channel</i>, which, |
| borrowing from CSP's descendants, represents a communications |
| channel that can connect two concurrent computations. |
| In Go, channel variables are references to a run-time object that |
| coordinates the communication; as with maps and slices, use |
| <code>make</code> to create a new channel. |
| <p> |
| Here is the first function in <code>progs/sieve.go</code>: |
| <p> |
| <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'. |
| } |
| }</pre> |
| <p> |
| The <code>generate</code> function sends the sequence 2, 3, 4, 5, ... to its |
| argument channel, <code>ch</code>, using the binary communications operator <code><-</code>. |
| Channel operations block, so if there's no recipient for the value on <code>ch</code>, |
| the send operation will wait until one becomes available. |
| <p> |
| The <code>filter</code> function has three arguments: an input channel, an output |
| 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><!--{{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'. |
| } |
| } |
| }</pre> |
| <p> |
| The generator and filters execute concurrently. Go has |
| its own model of process/threads/light-weight processes/coroutines, |
| so to avoid notational confusion we call concurrently executing |
| computations in Go <i>goroutines</i>. To start a goroutine, |
| invoke the function, prefixing the call with the keyword <code>go</code>; |
| this starts the function running in parallel with the current |
| computation but in the same address space: |
| <p> |
| <pre> |
| go sum(hugeArray) // calculate sum in the background |
| </pre> |
| <p> |
| If you want to know when the calculation is done, pass a channel |
| on which it can report back: |
| <p> |
| <pre> |
| ch := make(chan int) |
| go sum(hugeArray, ch) |
| // ... do something else for a while |
| result := <-ch // wait for, and retrieve, result |
| </pre> |
| <p> |
| Back to our prime sieve. Here's how the sieve pipeline is stitched |
| together: |
| <p> |
| <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. |
| for i := 0; i < 100; i++ { // Print the first hundred primes. |
| prime := <-ch |
| fmt.Println(prime) |
| ch1 := make(chan int) |
| go filter(ch, ch1, prime) |
| ch = ch1 |
| } |
| }</pre> |
| <p> |
| The first line of <code>main</code> creates the initial channel to pass to <code>generate</code>, which it |
| then starts up. As each prime pops out of the channel, a new <code>filter</code> |
| is added to the pipeline and <i>its</i> output becomes the new value |
| of <code>ch</code>. |
| <p> |
| 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><!--{{code "progs/sieve1.go" `/func.generate/` `/^}/`}} |
| -->func generate() chan int { |
| ch := make(chan int) |
| go func() { |
| for i := 2; ; i++ { |
| ch <- i |
| } |
| }() |
| return ch |
| }</pre> |
| <p> |
| This version does all the setup internally. It creates the output |
| channel, launches a goroutine running a function literal, and |
| returns the channel to the caller. It is a factory for concurrent |
| execution, starting the goroutine and returning its connection. |
| <p> |
| The function literal notation used in the <code>go</code> statement allows us to construct an |
| anonymous function and invoke it on the spot. Notice that the local |
| variable <code>ch</code> is available to the function literal and lives on even |
| after <code>generate</code> returns. |
| <p> |
| The same change can be made to <code>filter</code>: |
| <p> |
| <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 { |
| out <- i |
| } |
| } |
| }() |
| return out |
| }</pre> |
| <p> |
| 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><!--{{code "progs/sieve1.go" `/func.sieve/` `/^}/`}} |
| -->func sieve() chan int { |
| out := make(chan int) |
| go func() { |
| ch := generate() |
| for { |
| prime := <-ch |
| out <- prime |
| ch = filter(ch, prime) |
| } |
| }() |
| return out |
| }</pre> |
| <p> |
| Now <code>main</code>'s interface to the prime sieve is a channel of primes: |
| <p> |
| <pre><!--{{code "progs/sieve1.go" `/func.main/` `/^}/`}} |
| -->func main() { |
| primes := sieve() |
| for i := 0; i < 100; i++ { // Print the first hundred primes. |
| fmt.Println(<-primes) |
| } |
| }</pre> |
| <p> |
| <h2>Multiplexing</h2> |
| <p> |
| With channels, it's possible to serve multiple independent client goroutines without |
| writing an explicit multiplexer. The trick is to send the server a channel in the message, |
| which it will then use to reply to the original sender. |
| A realistic client-server program is a lot of code, so here is a very simple substitute |
| 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><!--{{code "progs/server.go" `/type.request/` `/^}/`}} |
| -->type request struct { |
| 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><!--{{code "progs/server.go" `/type.binOp/` `/^}/`}} |
| -->type binOp func(a, b int) int |
| |
| func run(op binOp, req *request) { |
| reply := op(req.a, req.b) |
| req.replyc <- reply |
| }</pre> |
| <p> |
| The type declaration makes <code>binOp</code> represent a function taking two integers and |
| returning a third. |
| <p> |
| 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><!--{{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 |
| } |
| }</pre> |
| <p> |
| There's a new feature in the signature of <code>server</code>: the type of the |
| <code>service</code> channel specifies the direction of communication. |
| A channel of plain <code>chan</code> type can be used both for sending and receiving. |
| However, the type used when declaring a channel can be decorated with an arrow to |
| indicate that the channel can be used only to send (<code>chan<-</code>) or to |
| receive (<code><-chan</code>) data. |
| The arrow points towards or away from the <code>chan</code> to indicate whether data flows into or out of |
| the channel. |
| In the <code>server</code> function, <code>service <-chan *request</code> is a "receive only" channel |
| that the function can use only to <em>read</em> new requests. |
| <p> |
| We instantiate a server in a familiar way, starting it and returning a channel |
| connected to it: |
| <p> |
| <pre><!--{{code "progs/server.go" `/func.startServer/` `/^}/`}} |
| -->func startServer(op binOp) chan<- *request { |
| req := make(chan *request) |
| go server(op, req) |
| return req |
| }</pre> |
| <p> |
| The returned channel is send only, even though the channel was created bidirectionally. |
| The read end is passed to <code>server</code>, while the send end is returned |
| to the caller of <code>startServer</code>, so the two halves of the channel |
| are distinguished, just as we did in <code>startServer</code>. |
| <p> |
| Bidirectional channels can be assigned to unidirectional channels but not the |
| other way around, so if you annotate your channel directions when you declare |
| them, such as in function signatures, the type system can help you set up and |
| use channels correctly. |
| Note that it's pointless to <code>make</code> unidirectional channels, since you can't |
| use them to communicate. Their purpose is served by variables assigned from bidirectional channels |
| to distinguish the input and output halves. |
| <p> |
| Here's a simple test. It starts a server with an addition operator and sends out |
| <code>N</code> requests without waiting for the replies. Only after all the requests are sent |
| does it check the results. |
| <p> |
| <pre><!--{{code "progs/server.go" `/func.main/` `/^}/`}} |
| -->func main() { |
| adder := startServer(func(a, b int) int { return a + b }) |
| const N = 100 |
| var reqs [N]request |
| for i := 0; i < N; i++ { |
| req := &reqs[i] |
| req.a = i |
| req.b = i + N |
| 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 { |
| fmt.Println("fail at", i) |
| } |
| } |
| fmt.Println("done") |
| }</pre> |
| <p> |
| One annoyance with this program is that it doesn't shut down the server cleanly; when <code>main</code> returns |
| 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><!--{{code "progs/server1.go" `/func.startServer/` `/^}/`}} |
| -->func startServer(op binOp) (service chan *request, quit chan bool) { |
| service = make(chan *request) |
| quit = make(chan bool) |
| go server(op, service, quit) |
| return service, quit |
| }</pre> |
| <p> |
| It passes the quit channel to the <code>server</code> function, which uses it like this: |
| <p> |
| <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 |
| case <-quit: |
| return |
| } |
| } |
| }</pre> |
| <p> |
| Inside <code>server</code>, the <code>select</code> statement chooses which of the multiple communications |
| listed by its cases can proceed. If all are blocked, it waits until one can proceed; if |
| multiple can proceed, it chooses one at random. In this instance, the <code>select</code> allows |
| the server to honor requests until it receives a quit message, at which point it |
| returns, terminating its execution. |
| <p> |
| <p> |
| All that's left is to strobe the <code>quit</code> channel |
| at the end of main: |
| <p> |
| <pre><!--{{code "progs/server1.go" `/adder,.quit/`}} |
| --> adder, quit := startServer(func(a, b int) int { return a + b })</pre> |
| ... |
| <pre><!--{{code "progs/server1.go" `/quit....true/`}} |
| --> quit <- true</pre> |
| <p> |
| There's a lot more to Go programming and concurrent programming in general but this |
| quick tour should give you some of the basics. |