Rob Pike | cf16443 | 2009-11-12 11:05:20 -0800 | [diff] [blame] | 1 | <!-- A Tutorial for the Go Programming Language --> |
Rob Pike | bf983a0 | 2009-10-13 22:10:16 -0700 | [diff] [blame] | 2 | Introduction |
Rob Pike | ae4123f | 2008-09-10 11:46:05 -0700 | [diff] [blame] | 3 | ---- |
| 4 | |
Rob Pike | 83f0b71 | 2009-11-01 20:47:03 -0800 | [diff] [blame] | 5 | This document is a tutorial introduction to the basics of the Go programming |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 6 | language, intended for programmers familiar with C or C++. It is not a comprehensive |
Rob Pike | 327b6c6 | 2009-10-13 18:01:24 -0700 | [diff] [blame] | 7 | guide to the language; at the moment the document closest to that is the |
Rob Pike | 83f0b71 | 2009-11-01 20:47:03 -0800 | [diff] [blame] | 8 | <a href='/doc/go_spec.html'>language specification</a>. |
Rob Pike | 7115eef | 2011-02-14 11:25:00 -0800 | [diff] [blame] | 9 | After you've read this tutorial, you should look at |
Rob Pike | 83f0b71 | 2009-11-01 20:47:03 -0800 | [diff] [blame] | 10 | <a href='/doc/effective_go.html'>Effective Go</a>, |
Rob Pike | 7115eef | 2011-02-14 11:25:00 -0800 | [diff] [blame] | 11 | which digs deeper into how the language is used and |
| 12 | talks about the style and idioms of programming in Go. |
| 13 | Also, slides from a 3-day course about Go are available. |
Rob Pike | 9b409ac | 2011-06-10 15:05:51 +1000 | [diff] [blame] | 14 | They provide some background and a lot of examples: |
Rob Pike | 0d93dbc | 2009-11-08 22:03:12 -0800 | [diff] [blame] | 15 | <a href='/doc/GoCourseDay1.pdf'>Day 1</a>, |
| 16 | <a href='/doc/GoCourseDay2.pdf'>Day 2</a>, |
| 17 | <a href='/doc/GoCourseDay3.pdf'>Day 3</a>. |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 18 | |
Rob Pike | 83f0b71 | 2009-11-01 20:47:03 -0800 | [diff] [blame] | 19 | The presentation here proceeds through a series of modest programs to illustrate |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 20 | key features of the language. All the programs work (at time of writing) and are |
Rob Pike | bf983a0 | 2009-10-13 22:10:16 -0700 | [diff] [blame] | 21 | checked into the repository in the directory <a href='/doc/progs'>"/doc/progs/"</a>. |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 22 | |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 23 | Hello, World |
| 24 | ---- |
| 25 | |
| 26 | Let's start in the usual way: |
Rob Pike | ae4123f | 2008-09-10 11:46:05 -0700 | [diff] [blame] | 27 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 28 | !src progs/helloworld.go /package/ $ |
Rob Pike | ae4123f | 2008-09-10 11:46:05 -0700 | [diff] [blame] | 29 | |
Rob Pike | 6aabf31 | 2009-02-04 15:13:07 -0800 | [diff] [blame] | 30 | Every Go source file declares, using a "package" statement, which package it's part of. |
Ian Lance Taylor | 97a55a7 | 2009-11-08 21:00:45 -0800 | [diff] [blame] | 31 | It may also import other packages to use their facilities. |
Rob Pike | bdbb3b4 | 2009-03-18 14:09:16 -0700 | [diff] [blame] | 32 | This program imports the package "fmt" to gain access to |
Ian Lance Taylor | 97a55a7 | 2009-11-08 21:00:45 -0800 | [diff] [blame] | 33 | our old, now capitalized and package-qualified, friend, "fmt.Printf". |
Rob Pike | ae4123f | 2008-09-10 11:46:05 -0700 | [diff] [blame] | 34 | |
Ian Lance Taylor | 97a55a7 | 2009-11-08 21:00:45 -0800 | [diff] [blame] | 35 | Functions are introduced with the "func" keyword. |
| 36 | The "main" package's "main" function is where the program starts running (after |
| 37 | any initialization). |
Rob Pike | ae4123f | 2008-09-10 11:46:05 -0700 | [diff] [blame] | 38 | |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 39 | String constants can contain Unicode characters, encoded in UTF-8. |
| 40 | (In fact, Go source files are defined to be encoded in UTF-8.) |
Rob Pike | ae4123f | 2008-09-10 11:46:05 -0700 | [diff] [blame] | 41 | |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 42 | The comment convention is the same as in C++: |
| 43 | |
| 44 | /* ... */ |
| 45 | // ... |
| 46 | |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 47 | Later we'll have much more to say about printing. |
| 48 | |
Rob Pike | 34356e9 | 2009-12-16 10:29:53 +1100 | [diff] [blame] | 49 | Semicolons |
| 50 | ---- |
| 51 | |
| 52 | You might have noticed that our program has no semicolons. In Go |
| 53 | code, the only place you typically see semicolons is separating the |
| 54 | clauses of "for" loops and the like; they are not necessary after |
| 55 | every statement. |
| 56 | |
| 57 | In fact, what happens is that the formal language uses semicolons, |
| 58 | much as in C or Java, but they are inserted automatically |
| 59 | at the end of every line that looks like the end of a statement. You |
| 60 | don't need to type them yourself. |
| 61 | |
| 62 | For details about how this is done you can see the language |
| 63 | specification, but in practice all you need to know is that you |
| 64 | never need to put a semicolon at the end of a line. (You can put |
| 65 | them in if you want to write multiple statements per line.) As an |
| 66 | extra help, you can also leave out a semicolon immediately before |
| 67 | a closing brace. |
| 68 | |
| 69 | This approach makes for clean-looking, semicolon-free code. The |
| 70 | one surprise is that it's important to put the opening |
| 71 | brace of a construct such as an "if" statement on the same line as |
| 72 | the "if"; if you don't, there are situations that may not compile |
| 73 | or may give the wrong result. The language forces the brace style |
| 74 | to some extent. |
| 75 | |
Rob Pike | 83f0b71 | 2009-11-01 20:47:03 -0800 | [diff] [blame] | 76 | Compiling |
| 77 | ---- |
| 78 | |
| 79 | Go is a compiled language. At the moment there are two compilers. |
| 80 | "Gccgo" is a Go compiler that uses the GCC back end. There is also a |
| 81 | suite of compilers with different (and odd) names for each architecture: |
| 82 | "6g" for the 64-bit x86, "8g" for the 32-bit x86, and more. These |
| 83 | compilers run significantly faster but generate less efficient code |
| 84 | than "gccgo". At the time of writing (late 2009), they also have |
| 85 | a more robust run-time system although "gccgo" is catching up. |
| 86 | |
| 87 | Here's how to compile and run our program. With "6g", say, |
| 88 | |
| 89 | $ 6g helloworld.go # compile; object goes into helloworld.6 |
| 90 | $ 6l helloworld.6 # link; output goes into 6.out |
| 91 | $ 6.out |
| 92 | Hello, world; or Καλημέρα κόσμε; or こんにちは 世界 |
| 93 | $ |
| 94 | |
| 95 | With "gccgo" it looks a little more traditional. |
| 96 | |
| 97 | $ gccgo helloworld.go |
| 98 | $ a.out |
| 99 | Hello, world; or Καλημέρα κόσμε; or こんにちは 世界 |
| 100 | $ |
| 101 | |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 102 | Echo |
| 103 | ---- |
| 104 | |
| 105 | Next up, here's a version of the Unix utility "echo(1)": |
| 106 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 107 | !src progs/echo.go /package/ $ |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 108 | |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 109 | This program is small but it's doing a number of new things. In the last example, |
Rob Pike | 83f0b71 | 2009-11-01 20:47:03 -0800 | [diff] [blame] | 110 | we saw "func" introduce a function. The keywords "var", "const", and "type" |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 111 | (not used yet) also introduce declarations, as does "import". |
| 112 | Notice that we can group declarations of the same sort into |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 113 | parenthesized lists, one item per line, as in the "import" and "const" clauses here. |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 114 | But it's not necessary to do so; we could have said |
| 115 | |
| 116 | const Space = " " |
| 117 | const Newline = "\n" |
| 118 | |
Rob Pike | bdbb3b4 | 2009-03-18 14:09:16 -0700 | [diff] [blame] | 119 | This program imports the ""os"" package to access its "Stdout" variable, of type |
| 120 | "*os.File". The "import" statement is actually a declaration: in its general form, |
| 121 | as used in our ``hello world'' program, |
| 122 | it names the identifier ("fmt") |
| 123 | that will be used to access members of the package imported from the file (""fmt""), |
| 124 | found in the current directory or in a standard location. |
| 125 | In this program, though, we've dropped the explicit name from the imports; by default, |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 126 | packages are imported using the name defined by the imported package, |
Rob Pike | bdbb3b4 | 2009-03-18 14:09:16 -0700 | [diff] [blame] | 127 | which by convention is of course the file name itself. Our ``hello world'' program |
| 128 | could have said just "import "fmt"". |
| 129 | |
| 130 | You can specify your |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 131 | own import names if you want but it's only necessary if you need to resolve |
| 132 | a naming conflict. |
| 133 | |
Rob Pike | bdbb3b4 | 2009-03-18 14:09:16 -0700 | [diff] [blame] | 134 | Given "os.Stdout" we can use its "WriteString" method to print the string. |
| 135 | |
Rob Pike | c17347e | 2011-07-09 23:17:38 +1000 | [diff] [blame] | 136 | After importing the "flag" package, we use a "var" declaration |
| 137 | to create and initialize a global variable, called "omitNewline", |
| 138 | to hold the value of echo's "-n" flag. |
| 139 | The variable has type "*bool", pointer to "bool". |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 140 | |
Rob Pike | c17347e | 2011-07-09 23:17:38 +1000 | [diff] [blame] | 141 | In "main.main", we parse the arguments (the call to "flag.Parse") and then create a local |
| 142 | string variable with which to build the output. |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 143 | |
| 144 | The declaration statement has the form |
| 145 | |
Andrew Gerrand | a823496 | 2010-04-28 10:50:44 +1000 | [diff] [blame] | 146 | var s string = "" |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 147 | |
| 148 | This is the "var" keyword, followed by the name of the variable, followed by |
| 149 | its type, followed by an equals sign and an initial value for the variable. |
| 150 | |
| 151 | Go tries to be terse, and this declaration could be shortened. Since the |
| 152 | string constant is of type string, we don't have to tell the compiler that. |
| 153 | We could write |
| 154 | |
Andrew Gerrand | a823496 | 2010-04-28 10:50:44 +1000 | [diff] [blame] | 155 | var s = "" |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 156 | |
| 157 | or we could go even shorter and write the idiom |
| 158 | |
Andrew Gerrand | a823496 | 2010-04-28 10:50:44 +1000 | [diff] [blame] | 159 | s := "" |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 160 | |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 161 | The ":=" operator is used a lot in Go to represent an initializing declaration. |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 162 | There's one in the "for" clause on the next line: |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 163 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 164 | !src progs/echo.go /for/ |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 165 | |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 166 | The "flag" package has parsed the arguments and left the non-flag arguments |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 167 | in a list that can be iterated over in the obvious way. |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 168 | |
| 169 | The Go "for" statement differs from that of C in a number of ways. First, |
| 170 | it's the only looping construct; there is no "while" or "do". Second, |
| 171 | there are no parentheses on the clause, but the braces on the body |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 172 | are mandatory. The same applies to the "if" and "switch" statements. |
| 173 | Later examples will show some other ways "for" can be written. |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 174 | |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 175 | The body of the loop builds up the string "s" by appending (using "+=") |
Rob Pike | f81abb9 | 2010-06-05 12:06:18 -0700 | [diff] [blame] | 176 | the arguments and separating spaces. After the loop, if the "-n" flag is not |
Rob Pike | 83f0b71 | 2009-11-01 20:47:03 -0800 | [diff] [blame] | 177 | set, the program appends a newline. Finally, it writes the result. |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 178 | |
| 179 | Notice that "main.main" is a niladic function with no return type. |
| 180 | It's defined that way. Falling off the end of "main.main" means |
Rob Pike | 6102877 | 2009-08-13 08:54:26 -0700 | [diff] [blame] | 181 | ''success''; if you want to signal an erroneous return, call |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 182 | |
Rob Pike | 6102877 | 2009-08-13 08:54:26 -0700 | [diff] [blame] | 183 | os.Exit(1) |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 184 | |
Rob Pike | 6102877 | 2009-08-13 08:54:26 -0700 | [diff] [blame] | 185 | The "os" package contains other essentials for getting |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 186 | started; for instance, "os.Args" is a slice used by the |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 187 | "flag" package to access the command-line arguments. |
Rob Pike | 27a5617 | 2008-09-10 17:11:04 -0700 | [diff] [blame] | 188 | |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 189 | An Interlude about Types |
| 190 | ---- |
| 191 | |
Rob Pike | 80e25fc | 2011-01-19 23:07:38 -0500 | [diff] [blame] | 192 | Go has some familiar types such as "int" and "uint" (unsigned "int"), which represent |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 193 | values of the ''appropriate'' size for the machine. It also defines |
Ian Lance Taylor | 97a55a7 | 2009-11-08 21:00:45 -0800 | [diff] [blame] | 194 | explicitly-sized types such as "int8", "float64", and so on, plus |
Rob Pike | 80e25fc | 2011-01-19 23:07:38 -0500 | [diff] [blame] | 195 | unsigned integer types such as "uint", "uint32", etc. |
| 196 | These are distinct types; even if "int" and "int32" are both 32 bits in size, |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 197 | they are not the same type. There is also a "byte" synonym for |
| 198 | "uint8", which is the element type for strings. |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 199 | |
Rob Pike | 80e25fc | 2011-01-19 23:07:38 -0500 | [diff] [blame] | 200 | Floating-point types are always sized: "float32" and "float64", |
| 201 | plus "complex64" (two "float32s") and "complex128" |
| 202 | (two "float64s"). Complex numbers are outside the |
| 203 | scope of this tutorial. |
| 204 | |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 205 | Speaking of "string", that's a built-in type as well. Strings are |
Ian Lance Taylor | 97a55a7 | 2009-11-08 21:00:45 -0800 | [diff] [blame] | 206 | <i>immutable values</i>—they are not just arrays of "byte" values. |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 207 | Once you've built a string <i>value</i>, you can't change it, although |
| 208 | of course you can change a string <i>variable</i> simply by |
| 209 | reassigning it. This snippet from "strings.go" is legal code: |
| 210 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 211 | !src progs/strings.go /hello/ /ciao/ |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 212 | |
| 213 | However the following statements are illegal because they would modify |
| 214 | a "string" value: |
| 215 | |
Andrew Gerrand | a823496 | 2010-04-28 10:50:44 +1000 | [diff] [blame] | 216 | s[0] = 'x' |
| 217 | (*p)[1] = 'y' |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 218 | |
| 219 | In C++ terms, Go strings are a bit like "const strings", while pointers |
| 220 | to strings are analogous to "const string" references. |
| 221 | |
| 222 | Yes, there are pointers. However, Go simplifies their use a little; |
| 223 | read on. |
| 224 | |
| 225 | Arrays are declared like this: |
| 226 | |
Andrew Gerrand | a823496 | 2010-04-28 10:50:44 +1000 | [diff] [blame] | 227 | var arrayOfInt [10]int |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 228 | |
| 229 | Arrays, like strings, are values, but they are mutable. This differs |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 230 | from C, in which "arrayOfInt" would be usable as a pointer to "int". |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 231 | In Go, since arrays are values, it's meaningful (and useful) to talk |
| 232 | about pointers to arrays. |
| 233 | |
| 234 | The size of the array is part of its type; however, one can declare |
Rob Pike | 781462d | 2010-09-10 13:53:18 +1000 | [diff] [blame] | 235 | a <i>slice</i> variable to hold a reference to any array, of any size, |
| 236 | with the same element type. |
| 237 | A <i>slice |
| 238 | expression</i> has the form "a[low : high]", representing |
| 239 | the internal array indexed from "low" through "high-1"; the resulting |
| 240 | slice is indexed from "0" through "high-low-1". |
| 241 | In short, slices look a lot like arrays but with |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 242 | no explicit size ("[]" vs. "[10]") and they reference a segment of |
Rob Pike | 781462d | 2010-09-10 13:53:18 +1000 | [diff] [blame] | 243 | an underlying, usually anonymous, regular array. Multiple slices |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 244 | can share data if they represent pieces of the same array; |
| 245 | multiple arrays can never share data. |
| 246 | |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 247 | Slices are much more common in Go programs than |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 248 | regular arrays; they're more flexible, have reference semantics, |
| 249 | and are efficient. What they lack is the precise control of storage |
| 250 | layout of a regular array; if you want to have a hundred elements |
| 251 | of an array stored within your structure, you should use a regular |
Rob Pike | 781462d | 2010-09-10 13:53:18 +1000 | [diff] [blame] | 252 | array. To create one, use a compound value <i>constructor</i>—an |
| 253 | expression formed |
| 254 | from a type followed by a brace-bounded expression like this: |
| 255 | |
| 256 | [3]int{1,2,3} |
| 257 | |
| 258 | In this case the constructor builds an array of 3 "ints". |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 259 | |
| 260 | When passing an array to a function, you almost always want |
Rob Pike | dfff182 | 2009-04-15 20:53:07 -0700 | [diff] [blame] | 261 | to declare the formal parameter to be a slice. When you call |
Rob Pike | 781462d | 2010-09-10 13:53:18 +1000 | [diff] [blame] | 262 | the function, slice the array to create |
| 263 | (efficiently) a slice reference and pass that. |
| 264 | By default, the lower and upper bounds of a slice match the |
| 265 | ends of the existing object, so the concise notation "[:]" |
| 266 | will slice the whole array. |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 267 | |
| 268 | Using slices one can write this function (from "sum.go"): |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 269 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 270 | !src progs/sum.go /sum/ /^}/ |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 271 | |
Rob Pike | 46f482a | 2011-05-25 06:44:09 +1000 | [diff] [blame] | 272 | Note how the return type ("int") is defined for "sum" by stating it |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 273 | after the parameter list. |
Rob Pike | 781462d | 2010-09-10 13:53:18 +1000 | [diff] [blame] | 274 | |
| 275 | To call the function, we slice the array. This intricate call (we'll show |
| 276 | a simpler way in a moment) constructs |
| 277 | an array and slices it: |
| 278 | |
| 279 | s := sum([3]int{1,2,3}[:]) |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 280 | |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 281 | If you are creating a regular array but want the compiler to count the |
| 282 | elements for you, use "..." as the array size: |
| 283 | |
Rob Pike | 781462d | 2010-09-10 13:53:18 +1000 | [diff] [blame] | 284 | s := sum([...]int{1,2,3}[:]) |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 285 | |
Rob Pike | 781462d | 2010-09-10 13:53:18 +1000 | [diff] [blame] | 286 | That's fussier than necessary, though. |
| 287 | In practice, unless you're meticulous about storage layout within a |
| 288 | data structure, a slice itself—using empty brackets with no size—is all you need: |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 289 | |
Andrew Gerrand | a823496 | 2010-04-28 10:50:44 +1000 | [diff] [blame] | 290 | s := sum([]int{1,2,3}) |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 291 | |
| 292 | There are also maps, which you can initialize like this: |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 293 | |
Rob Pike | 83f0b71 | 2009-11-01 20:47:03 -0800 | [diff] [blame] | 294 | m := map[string]int{"one":1 , "two":2} |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 295 | |
Rob Pike | 46f482a | 2011-05-25 06:44:09 +1000 | [diff] [blame] | 296 | The built-in function "len", which returns number of elements, |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 297 | makes its first appearance in "sum". It works on strings, arrays, |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 298 | slices, maps, and channels. |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 299 | |
Rob Pike | cf16443 | 2009-11-12 11:05:20 -0800 | [diff] [blame] | 300 | By the way, another thing that works on strings, arrays, slices, maps |
| 301 | and channels is the "range" clause on "for" loops. Instead of writing |
| 302 | |
Rob Pike | bbd4cb3 | 2009-12-14 13:30:11 +1100 | [diff] [blame] | 303 | for i := 0; i < len(a); i++ { ... } |
Rob Pike | cf16443 | 2009-11-12 11:05:20 -0800 | [diff] [blame] | 304 | |
| 305 | to loop over the elements of a slice (or map or ...) , we could write |
| 306 | |
| 307 | for i, v := range a { ... } |
| 308 | |
| 309 | This assigns "i" to the index and "v" to the value of the successive |
| 310 | elements of the target of the range. See |
| 311 | <a href='/doc/effective_go.html'>Effective Go</a> |
| 312 | for more examples of its use. |
| 313 | |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 314 | |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 315 | An Interlude about Allocation |
| 316 | ---- |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 317 | |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 318 | Most types in Go are values. If you have an "int" or a "struct" |
| 319 | or an array, assignment |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 320 | copies the contents of the object. |
Rob Pike | 46f482a | 2011-05-25 06:44:09 +1000 | [diff] [blame] | 321 | To allocate a new variable, use the built-in function "new", which |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 322 | returns a pointer to the allocated storage. |
| 323 | |
| 324 | type T struct { a, b int } |
Andrew Gerrand | a823496 | 2010-04-28 10:50:44 +1000 | [diff] [blame] | 325 | var t *T = new(T) |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 326 | |
| 327 | or the more idiomatic |
| 328 | |
Andrew Gerrand | a823496 | 2010-04-28 10:50:44 +1000 | [diff] [blame] | 329 | t := new(T) |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 330 | |
Ian Lance Taylor | 97a55a7 | 2009-11-08 21:00:45 -0800 | [diff] [blame] | 331 | Some types—maps, slices, and channels (see below)—have reference semantics. |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 332 | If you're holding a slice or a map and you modify its contents, other variables |
Rob Pike | 6aabf31 | 2009-02-04 15:13:07 -0800 | [diff] [blame] | 333 | referencing the same underlying data will see the modification. For these three |
Rob Pike | 46f482a | 2011-05-25 06:44:09 +1000 | [diff] [blame] | 334 | types you want to use the built-in function "make": |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 335 | |
Andrew Gerrand | a823496 | 2010-04-28 10:50:44 +1000 | [diff] [blame] | 336 | m := make(map[string]int) |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 337 | |
Rob Pike | 6aabf31 | 2009-02-04 15:13:07 -0800 | [diff] [blame] | 338 | This statement initializes a new map ready to store entries. |
| 339 | If you just declare the map, as in |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 340 | |
Andrew Gerrand | a823496 | 2010-04-28 10:50:44 +1000 | [diff] [blame] | 341 | var m map[string]int |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 342 | |
Rob Pike | 6aabf31 | 2009-02-04 15:13:07 -0800 | [diff] [blame] | 343 | it creates a "nil" reference that cannot hold anything. To use the map, |
Rob Pike | 46f482a | 2011-05-25 06:44:09 +1000 | [diff] [blame] | 344 | you must first initialize the reference using "make" or by assignment from an |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 345 | existing map. |
| 346 | |
Rob Pike | 6aabf31 | 2009-02-04 15:13:07 -0800 | [diff] [blame] | 347 | Note that "new(T)" returns type "*T" while "make(T)" returns type |
Rob Pike | 46f482a | 2011-05-25 06:44:09 +1000 | [diff] [blame] | 348 | "T". If you (mistakenly) allocate a reference object with "new" rather than "make", |
Ian Lance Taylor | 97a55a7 | 2009-11-08 21:00:45 -0800 | [diff] [blame] | 349 | you receive a pointer to a nil reference, equivalent to |
Rob Pike | 6aabf31 | 2009-02-04 15:13:07 -0800 | [diff] [blame] | 350 | declaring an uninitialized variable and taking its address. |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 351 | |
| 352 | An Interlude about Constants |
| 353 | ---- |
| 354 | |
| 355 | Although integers come in lots of sizes in Go, integer constants do not. |
Rob Pike | 83f0b71 | 2009-11-01 20:47:03 -0800 | [diff] [blame] | 356 | There are no constants like "0LL" or "0x0UL". Instead, integer |
Robert Griesemer | 8403330 | 2009-10-01 16:58:17 -0700 | [diff] [blame] | 357 | constants are evaluated as large-precision values that |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 358 | can overflow only when they are assigned to an integer variable with |
| 359 | too little precision to represent the value. |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 360 | |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 361 | const hardEight = (1 << 100) >> 97 // legal |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 362 | |
| 363 | There are nuances that deserve redirection to the legalese of the |
| 364 | language specification but here are some illustrative examples: |
| 365 | |
| 366 | var a uint64 = 0 // a has type uint64, value 0 |
Ian Lance Taylor | 97a55a7 | 2009-11-08 21:00:45 -0800 | [diff] [blame] | 367 | a := uint64(0) // equivalent; uses a "conversion" |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 368 | i := 0x1234 // i gets default type: int |
| 369 | var j int = 1e6 // legal - 1000000 is representable in an int |
Rob Pike | 80e25fc | 2011-01-19 23:07:38 -0500 | [diff] [blame] | 370 | x := 1.5 // a float64, the default type for floating constants |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 371 | i3div2 := 3/2 // integer division - result is 1 |
Rob Pike | 80e25fc | 2011-01-19 23:07:38 -0500 | [diff] [blame] | 372 | f3div2 := 3./2. // floating-point division - result is 1.5 |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 373 | |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 374 | Conversions only work for simple cases such as converting "ints" of one |
Rob Pike | 80e25fc | 2011-01-19 23:07:38 -0500 | [diff] [blame] | 375 | sign or size to another and between integers and floating-point numbers, |
| 376 | plus a couple of other instances outside the scope of a tutorial. |
| 377 | There are no automatic numeric conversions of any kind in Go, |
Rob Pike | c7ebfed | 2008-09-11 10:21:02 -0700 | [diff] [blame] | 378 | other than that of making constants have concrete size and type when |
| 379 | assigned to a variable. |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 380 | |
| 381 | An I/O Package |
| 382 | ---- |
| 383 | |
Rob Pike | 23fc9c8 | 2011-04-18 10:51:40 -0700 | [diff] [blame] | 384 | Next we'll look at a simple package for doing file I/O with an |
| 385 | open/close/read/write interface. Here's the start of "file.go": |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 386 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 387 | !src progs/file.go /package/ /^}/ |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 388 | |
Ian Lance Taylor | 97a55a7 | 2009-11-08 21:00:45 -0800 | [diff] [blame] | 389 | The first few lines declare the name of the |
| 390 | package—"file"—and then import two packages. The "os" |
| 391 | package hides the differences |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 392 | between various operating systems to give a consistent view of files and |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 393 | so on; here we're going to use its error handling utilities |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 394 | and reproduce the rudiments of its file I/O. |
| 395 | |
| 396 | The other item is the low-level, external "syscall" package, which provides |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 397 | a primitive interface to the underlying operating system's calls. |
| 398 | |
| 399 | Next is a type definition: the "type" keyword introduces a type declaration, |
Rob Pike | e9f4fb2 | 2009-03-16 22:53:23 -0700 | [diff] [blame] | 400 | in this case a data structure called "File". |
| 401 | To make things a little more interesting, our "File" includes the name of the file |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 402 | that the file descriptor refers to. |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 403 | |
Rob Pike | e9f4fb2 | 2009-03-16 22:53:23 -0700 | [diff] [blame] | 404 | Because "File" starts with a capital letter, the type is available outside the package, |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 405 | that is, by users of the package. In Go the rule about visibility of information is |
Rob Pike | 83f0b71 | 2009-11-01 20:47:03 -0800 | [diff] [blame] | 406 | simple: if a name (of a top-level type, function, method, constant or variable, or of |
| 407 | a structure field or method) is capitalized, users of the package may see it. Otherwise, the |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 408 | name and hence the thing being named is visible only inside the package in which |
Rob Pike | 6aabf31 | 2009-02-04 15:13:07 -0800 | [diff] [blame] | 409 | it is declared. This is more than a convention; the rule is enforced by the compiler. |
| 410 | In Go, the term for publicly visible names is ''exported''. |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 411 | |
Rob Pike | e9f4fb2 | 2009-03-16 22:53:23 -0700 | [diff] [blame] | 412 | In the case of "File", all its fields are lower case and so invisible to users, but we |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 413 | will soon give it some exported, upper-case methods. |
| 414 | |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 415 | First, though, here is a factory to create a "File": |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 416 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 417 | !src progs/file.go /newFile/ /^}/ |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 418 | |
Rob Pike | e9f4fb2 | 2009-03-16 22:53:23 -0700 | [diff] [blame] | 419 | This returns a pointer to a new "File" structure with the file descriptor and name |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 420 | filled in. This code uses Go's notion of a ''composite literal'', analogous to |
Rob Pike | 6aabf31 | 2009-02-04 15:13:07 -0800 | [diff] [blame] | 421 | the ones used to build maps and arrays, to construct a new heap-allocated |
| 422 | object. We could write |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 423 | |
Andrew Gerrand | a823496 | 2010-04-28 10:50:44 +1000 | [diff] [blame] | 424 | n := new(File) |
| 425 | n.fd = fd |
| 426 | n.name = name |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 427 | return n |
| 428 | |
Andrew Gerrand | 7de5e6e | 2010-10-21 14:59:23 +1100 | [diff] [blame] | 429 | but for simple structures like "File" it's easier to return the address of a |
Rob Pike | c17347e | 2011-07-09 23:17:38 +1000 | [diff] [blame] | 430 | composite literal, as is done here in the "return" statement from "newFile". |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 431 | |
Rob Pike | e9f4fb2 | 2009-03-16 22:53:23 -0700 | [diff] [blame] | 432 | We can use the factory to construct some familiar, exported variables of type "*File": |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 433 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 434 | !src progs/file.go /var/ /^.$/ |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 435 | |
Rob Pike | e9f4fb2 | 2009-03-16 22:53:23 -0700 | [diff] [blame] | 436 | The "newFile" function was not exported because it's internal. The proper, |
Rob Pike | 23fc9c8 | 2011-04-18 10:51:40 -0700 | [diff] [blame] | 437 | exported factory to use is "OpenFile" (we'll explain that name in a moment): |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 438 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 439 | !src progs/file.go /func.OpenFile/ /^}/ |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 440 | |
Rob Pike | 23fc9c8 | 2011-04-18 10:51:40 -0700 | [diff] [blame] | 441 | There are a number of new things in these few lines. First, "OpenFile" returns |
Rob Pike | cf16443 | 2009-11-12 11:05:20 -0800 | [diff] [blame] | 442 | multiple values, a "File" and an error (more about errors in a moment). |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 443 | We declare the |
| 444 | multi-value return as a parenthesized list of declarations; syntactically |
| 445 | they look just like a second parameter list. The function |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 446 | "syscall.Open" |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 447 | also has a multi-value return, which we can grab with the multi-variable |
Rob Pike | c17347e | 2011-07-09 23:17:38 +1000 | [diff] [blame] | 448 | declaration on the first line; it declares "r" and "e" to hold the two values, |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 449 | both of type "int" (although you'd have to look at the "syscall" package |
Rob Pike | c17347e | 2011-07-09 23:17:38 +1000 | [diff] [blame] | 450 | to see that). Finally, "OpenFile" returns two values: a pointer to the new "File" |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 451 | and the error. If "syscall.Open" fails, the file descriptor "r" will |
Rob Pike | 8f47890 | 2009-11-13 16:00:55 -0800 | [diff] [blame] | 452 | be negative and "newFile" will return "nil". |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 453 | |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 454 | About those errors: The "os" library includes a general notion of an error. |
| 455 | It's a good idea to use its facility in your own interfaces, as we do here, for |
Rob Pike | 6102877 | 2009-08-13 08:54:26 -0700 | [diff] [blame] | 456 | consistent error handling throughout Go code. In "Open" we use a |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 457 | conversion to translate Unix's integer "errno" value into the integer type |
| 458 | "os.Errno", which implements "os.Error". |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 459 | |
Rob Pike | 23fc9c8 | 2011-04-18 10:51:40 -0700 | [diff] [blame] | 460 | Why "OpenFile" and not "Open"? To mimic Go's "os" package, which |
| 461 | our exercise is emulating. The "os" package takes the opportunity |
| 462 | to make the two commonest cases - open for read and create for |
| 463 | write - the simplest, just "Open" and "Create". "OpenFile" is the |
| 464 | general case, analogous to the Unix system call "Open". Here is |
| 465 | the implementation of our "Open" and "Create"; they're trivial |
| 466 | wrappers that eliminate common errors by capturing |
| 467 | the tricky standard arguments to open and, especially, to create a file: |
| 468 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 469 | !src progs/file.go /^const/ /^}/ |
Rob Pike | 23fc9c8 | 2011-04-18 10:51:40 -0700 | [diff] [blame] | 470 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 471 | !src progs/file.go /func.Create/ /^}/ |
Rob Pike | 23fc9c8 | 2011-04-18 10:51:40 -0700 | [diff] [blame] | 472 | |
| 473 | Back to our main story. |
Rob Pike | e9f4fb2 | 2009-03-16 22:53:23 -0700 | [diff] [blame] | 474 | Now that we can build "Files", we can write methods for them. To declare |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 475 | a method of a type, we define a function to have an explicit receiver |
| 476 | of that type, placed |
Rob Pike | e9f4fb2 | 2009-03-16 22:53:23 -0700 | [diff] [blame] | 477 | in parentheses before the function name. Here are some methods for "*File", |
| 478 | each of which declares a receiver variable "file". |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 479 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 480 | !src progs/file.go /Close/ $ |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 481 | |
| 482 | There is no implicit "this" and the receiver variable must be used to access |
| 483 | members of the structure. Methods are not declared within |
| 484 | the "struct" declaration itself. The "struct" declaration defines only data members. |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 485 | In fact, methods can be created for almost any type you name, such as an integer or |
Rob Pike | 6aabf31 | 2009-02-04 15:13:07 -0800 | [diff] [blame] | 486 | array, not just for "structs". We'll see an example with arrays later. |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 487 | |
Rob Pike | 83f0b71 | 2009-11-01 20:47:03 -0800 | [diff] [blame] | 488 | The "String" method is so called because of a printing convention we'll |
Rob Pike | 6aabf31 | 2009-02-04 15:13:07 -0800 | [diff] [blame] | 489 | describe later. |
| 490 | |
Rob Pike | 6102877 | 2009-08-13 08:54:26 -0700 | [diff] [blame] | 491 | The methods use the public variable "os.EINVAL" to return the ("os.Error" |
| 492 | version of the) Unix error code "EINVAL". The "os" library defines a standard |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 493 | set of such error values. |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 494 | |
Rob Pike | 6102877 | 2009-08-13 08:54:26 -0700 | [diff] [blame] | 495 | We can now use our new package: |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 496 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 497 | !src progs/helloworld3.go /package/ $ |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 498 | |
Rob Pike | 708d716 | 2010-07-14 13:29:12 -0700 | [diff] [blame] | 499 | The ''"./"'' in the import of ''"./file"'' tells the compiler |
| 500 | to use our own package rather than |
Rob Pike | 6102877 | 2009-08-13 08:54:26 -0700 | [diff] [blame] | 501 | something from the directory of installed packages. |
Rob Pike | 708d716 | 2010-07-14 13:29:12 -0700 | [diff] [blame] | 502 | (Also, ''"file.go"'' must be compiled before we can import the |
| 503 | package.) |
Rob Pike | 6102877 | 2009-08-13 08:54:26 -0700 | [diff] [blame] | 504 | |
Rob Pike | eaade07 | 2011-01-18 11:07:02 -0800 | [diff] [blame] | 505 | Now we can compile and run the program. On Unix, this would be the result: |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 506 | |
Rob Pike | 708d716 | 2010-07-14 13:29:12 -0700 | [diff] [blame] | 507 | $ 6g file.go # compile file package |
| 508 | $ 6g helloworld3.go # compile main package |
| 509 | $ 6l -o helloworld3 helloworld3.6 # link - no need to mention "file" |
| 510 | $ helloworld3 |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 511 | hello, world |
Rob Pike | 6aabf31 | 2009-02-04 15:13:07 -0800 | [diff] [blame] | 512 | can't open file; err=No such file or directory |
Rob Pike | 708d716 | 2010-07-14 13:29:12 -0700 | [diff] [blame] | 513 | $ |
Rob Pike | 6693730 | 2008-09-12 16:03:16 -0700 | [diff] [blame] | 514 | |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 515 | Rotting cats |
| 516 | ---- |
| 517 | |
Rob Pike | e9f4fb2 | 2009-03-16 22:53:23 -0700 | [diff] [blame] | 518 | Building on the "file" package, here's a simple version of the Unix utility "cat(1)", |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 519 | "progs/cat.go": |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 520 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 521 | !src progs/cat.go /package/ $ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 522 | |
| 523 | By now this should be easy to follow, but the "switch" statement introduces some |
| 524 | new features. Like a "for" loop, an "if" or "switch" can include an |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 525 | initialization statement. The "switch" statement in "cat" uses one to create variables |
| 526 | "nr" and "er" to hold the return values from the call to "f.Read". (The "if" a few lines later |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 527 | has the same idea.) The "switch" statement is general: it evaluates the cases |
| 528 | from top to bottom looking for the first case that matches the value; the |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 529 | case expressions don't need to be constants or even integers, as long as |
| 530 | they all have the same type. |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 531 | |
Ian Lance Taylor | 97a55a7 | 2009-11-08 21:00:45 -0800 | [diff] [blame] | 532 | Since the "switch" value is just "true", we could leave it off—as is also |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 533 | the situation |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 534 | in a "for" statement, a missing value means "true". In fact, such a "switch" |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 535 | is a form of "if-else" chain. While we're here, it should be mentioned that in |
| 536 | "switch" statements each "case" has an implicit "break". |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 537 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 538 | The argument to "file.Stdout.Write" is created by slicing the array "buf". |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 539 | Slices provide the standard Go way to handle I/O buffers. |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 540 | |
| 541 | Now let's make a variant of "cat" that optionally does "rot13" on its input. |
| 542 | It's easy to do by just processing the bytes, but instead we will exploit |
| 543 | Go's notion of an <i>interface</i>. |
| 544 | |
Rob Pike | 46f482a | 2011-05-25 06:44:09 +1000 | [diff] [blame] | 545 | The "cat" subroutine uses only two methods of "f": "Read" and "String", |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 546 | so let's start by defining an interface that has exactly those two methods. |
| 547 | Here is code from "progs/cat_rot13.go": |
| 548 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 549 | !src progs/cat_rot13.go /type.reader/ /^}/ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 550 | |
Ian Lance Taylor | 97a55a7 | 2009-11-08 21:00:45 -0800 | [diff] [blame] | 551 | Any type that has the two methods of "reader"—regardless of whatever |
| 552 | other methods the type may also have—is said to <i>implement</i> the |
Rob Pike | e9f4fb2 | 2009-03-16 22:53:23 -0700 | [diff] [blame] | 553 | interface. Since "file.File" implements these methods, it implements the |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 554 | "reader" interface. We could tweak the "cat" subroutine to accept a "reader" |
Rob Pike | e9f4fb2 | 2009-03-16 22:53:23 -0700 | [diff] [blame] | 555 | instead of a "*file.File" and it would work just fine, but let's embellish a little |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 556 | first by writing a second type that implements "reader", one that wraps an |
| 557 | existing "reader" and does "rot13" on the data. To do this, we just define |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 558 | the type and implement the methods and with no other bookkeeping, |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 559 | we have a second implementation of the "reader" interface. |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 560 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 561 | !src progs/cat_rot13.go /type.rotate13/ /end.of.rotate13/ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 562 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 563 | (The "rot13" function called in "Read" is trivial and not worth reproducing here.) |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 564 | |
| 565 | To use the new feature, we define a flag: |
| 566 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 567 | !src progs/cat_rot13.go /rot13Flag/ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 568 | |
Rob Pike | 46f482a | 2011-05-25 06:44:09 +1000 | [diff] [blame] | 569 | and use it from within a mostly unchanged "cat" function: |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 570 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 571 | !src progs/cat_rot13.go /func.cat/ /^}/ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 572 | |
Rob Pike | 46f482a | 2011-05-25 06:44:09 +1000 | [diff] [blame] | 573 | (We could also do the wrapping in "main" and leave "cat" mostly alone, except |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 574 | for changing the type of the argument; consider that an exercise.) |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 575 | The "if" at the top of "cat" sets it all up: If the "rot13" flag is true, wrap the "reader" |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 576 | we received into a "rotate13" and proceed. Note that the interface variables |
| 577 | are values, not pointers: the argument is of type "reader", not "*reader", |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 578 | even though under the covers it holds a pointer to a "struct". |
| 579 | |
| 580 | Here it is in action: |
| 581 | |
Rob Pike | 708d716 | 2010-07-14 13:29:12 -0700 | [diff] [blame] | 582 | $ echo abcdefghijklmnopqrstuvwxyz | ./cat |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 583 | abcdefghijklmnopqrstuvwxyz |
Rob Pike | 708d716 | 2010-07-14 13:29:12 -0700 | [diff] [blame] | 584 | $ echo abcdefghijklmnopqrstuvwxyz | ./cat --rot13 |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 585 | nopqrstuvwxyzabcdefghijklm |
Rob Pike | 708d716 | 2010-07-14 13:29:12 -0700 | [diff] [blame] | 586 | $ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 587 | |
| 588 | Fans of dependency injection may take cheer from how easily interfaces |
Rob Pike | 81672ef | 2008-09-29 20:06:48 -0700 | [diff] [blame] | 589 | allow us to substitute the implementation of a file descriptor. |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 590 | |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 591 | Interfaces are a distinctive feature of Go. An interface is implemented by a |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 592 | type if the type implements all the methods declared in the interface. |
| 593 | This means |
| 594 | that a type may implement an arbitrary number of different interfaces. |
| 595 | There is no type hierarchy; things can be much more <i>ad hoc</i>, |
Rob Pike | e9f4fb2 | 2009-03-16 22:53:23 -0700 | [diff] [blame] | 596 | as we saw with "rot13". The type "file.File" implements "reader"; it could also |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 597 | implement a "writer", or any other interface built from its methods that |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 598 | fits the current situation. Consider the <i>empty interface</i> |
| 599 | |
Rob Pike | 6102877 | 2009-08-13 08:54:26 -0700 | [diff] [blame] | 600 | type Empty interface {} |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 601 | |
| 602 | <i>Every</i> type implements the empty interface, which makes it |
| 603 | useful for things like containers. |
| 604 | |
| 605 | Sorting |
| 606 | ---- |
| 607 | |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 608 | Interfaces provide a simple form of polymorphism. They completely |
Rob Pike | 6aabf31 | 2009-02-04 15:13:07 -0800 | [diff] [blame] | 609 | separate the definition of what an object does from how it does it, allowing |
| 610 | distinct implementations to be represented at different times by the |
| 611 | same interface variable. |
| 612 | |
| 613 | As an example, consider this simple sort algorithm taken from "progs/sort.go": |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 614 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 615 | !src progs/sort.go /func.Sort/ /^}/ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 616 | |
Rob Pike | 400fa1c | 2009-10-13 13:05:42 -0700 | [diff] [blame] | 617 | The code needs only three methods, which we wrap into sort's "Interface": |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 618 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 619 | !src progs/sort.go /interface/ /^}/ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 620 | |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 621 | We can apply "Sort" to any type that implements "Len", "Less", and "Swap". |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 622 | The "sort" package includes the necessary methods to allow sorting of |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 623 | arrays of integers, strings, etc.; here's the code for arrays of "int" |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 624 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 625 | !src progs/sort.go /type.*IntSlice/ /Swap/ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 626 | |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 627 | Here we see methods defined for non-"struct" types. You can define methods |
| 628 | for any type you define and name in your package. |
| 629 | |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 630 | And now a routine to test it out, from "progs/sortmain.go". This |
| 631 | uses a function in the "sort" package, omitted here for brevity, |
| 632 | to test that the result is sorted. |
| 633 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 634 | !src progs/sortmain.go /func.ints/ /^}/ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 635 | |
| 636 | If we have a new type we want to be able to sort, all we need to do is |
| 637 | to implement the three methods for that type, like this: |
| 638 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 639 | !src progs/sortmain.go /type.day/ /Swap/ |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 640 | |
| 641 | |
| 642 | Printing |
Rob Pike | bf983a0 | 2009-10-13 22:10:16 -0700 | [diff] [blame] | 643 | ---- |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 644 | |
| 645 | The examples of formatted printing so far have been modest. In this section |
| 646 | we'll talk about how formatted I/O can be done well in Go. |
| 647 | |
Rob Pike | bdbb3b4 | 2009-03-18 14:09:16 -0700 | [diff] [blame] | 648 | We've seen simple uses of the package "fmt", which |
| 649 | implements "Printf", "Fprintf", and so on. |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 650 | Within the "fmt" package, "Printf" is declared with this signature: |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 651 | |
Rob Pike | b905562 | 2010-06-14 12:27:22 -0700 | [diff] [blame] | 652 | Printf(format string, v ...interface{}) (n int, errno os.Error) |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 653 | |
Rob Pike | b905562 | 2010-06-14 12:27:22 -0700 | [diff] [blame] | 654 | The token "..." introduces a variable-length argument list that in C would |
| 655 | be handled using the "stdarg.h" macros. |
| 656 | In Go, variadic functions are passed a slice of the arguments of the |
| 657 | specified type. In "Printf"'s case, the declaration says "...interface{}" |
| 658 | so the actual type is a slice of empty interface values, "[]interface{}". |
| 659 | "Printf" can examine the arguments by iterating over the slice |
| 660 | and, for each element, using a type switch or the reflection library |
| 661 | to interpret the value. |
| 662 | It's off topic here but such run-time type analysis |
| 663 | helps explain some of the nice properties of Go's "Printf", |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 664 | due to the ability of "Printf" to discover the type of its arguments |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 665 | dynamically. |
| 666 | |
| 667 | For example, in C each format must correspond to the type of its |
| 668 | argument. It's easier in many cases in Go. Instead of "%llud" you |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 669 | can just say "%d"; "Printf" knows the size and signedness of the |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 670 | integer and can do the right thing for you. The snippet |
| 671 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 672 | !src progs/print.go 10 11 |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 673 | |
| 674 | prints |
| 675 | |
| 676 | 18446744073709551615 -1 |
| 677 | |
| 678 | In fact, if you're lazy the format "%v" will print, in a simple |
| 679 | appropriate style, any value, even an array or structure. The output of |
| 680 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 681 | !src progs/print.go 14 20 |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 682 | |
| 683 | is |
| 684 | |
| 685 | 18446744073709551615 {77 Sunset Strip} [1 2 3 4] |
| 686 | |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 687 | You can drop the formatting altogether if you use "Print" or "Println" |
| 688 | instead of "Printf". Those routines do fully automatic formatting. |
| 689 | The "Print" function just prints its elements out using the equivalent |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 690 | of "%v" while "Println" inserts spaces between arguments |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 691 | and adds a newline. The output of each of these two lines is identical |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 692 | to that of the "Printf" call above. |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 693 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 694 | !src progs/print.go 21 22 |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 695 | |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 696 | If you have your own type you'd like "Printf" or "Print" to format, |
Rob Pike | 46f482a | 2011-05-25 06:44:09 +1000 | [diff] [blame] | 697 | just give it a "String" method that returns a string. The print |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 698 | routines will examine the value to inquire whether it implements |
| 699 | the method and if so, use it rather than some other formatting. |
| 700 | Here's a simple example. |
| 701 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 702 | !src progs/print_string.go 9 $ |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 703 | |
Rob Pike | 46f482a | 2011-05-25 06:44:09 +1000 | [diff] [blame] | 704 | Since "*testType" has a "String" method, the |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 705 | default formatter for that type will use it and produce the output |
| 706 | |
| 707 | 77 Sunset Strip |
| 708 | |
Rob Pike | 46f482a | 2011-05-25 06:44:09 +1000 | [diff] [blame] | 709 | Observe that the "String" method calls "Sprint" (the obvious Go |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 710 | variant that returns a string) to do its formatting; special formatters |
| 711 | can use the "fmt" library recursively. |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 712 | |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 713 | Another feature of "Printf" is that the format "%T" will print a string |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 714 | representation of the type of a value, which can be handy when debugging |
| 715 | polymorphic code. |
| 716 | |
| 717 | It's possible to write full custom print formats with flags and precisions |
| 718 | and such, but that's getting a little off the main thread so we'll leave it |
| 719 | as an exploration exercise. |
| 720 | |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 721 | You might ask, though, how "Printf" can tell whether a type implements |
Rob Pike | 46f482a | 2011-05-25 06:44:09 +1000 | [diff] [blame] | 722 | the "String" method. Actually what it does is ask if the value can |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 723 | be converted to an interface variable that implements the method. |
| 724 | Schematically, given a value "v", it does this: |
| 725 | |
| 726 | |
Rob Pike | df46b33 | 2009-05-08 11:21:25 -0700 | [diff] [blame] | 727 | type Stringer interface { |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 728 | String() string |
| 729 | } |
| 730 | |
Andrew Gerrand | a823496 | 2010-04-28 10:50:44 +1000 | [diff] [blame] | 731 | s, ok := v.(Stringer) // Test whether v implements "String()" |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 732 | if ok { |
| 733 | result = s.String() |
| 734 | } else { |
Rob Pike | 83f0b71 | 2009-11-01 20:47:03 -0800 | [diff] [blame] | 735 | result = defaultOutput(v) |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 736 | } |
| 737 | |
Rob Pike | df46b33 | 2009-05-08 11:21:25 -0700 | [diff] [blame] | 738 | The code uses a ``type assertion'' ("v.(Stringer)") to test if the value stored in |
| 739 | "v" satisfies the "Stringer" interface; if it does, "s" |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 740 | will become an interface variable implementing the method and "ok" will |
| 741 | be "true". We then use the interface variable to call the method. |
| 742 | (The ''comma, ok'' pattern is a Go idiom used to test the success of |
| 743 | operations such as type conversion, map update, communications, and so on, |
| 744 | although this is the only appearance in this tutorial.) |
| 745 | If the value does not satisfy the interface, "ok" will be false. |
| 746 | |
Ian Lance Taylor | 97a55a7 | 2009-11-08 21:00:45 -0800 | [diff] [blame] | 747 | In this snippet the name "Stringer" follows the convention that we add ''[e]r'' |
Rob Pike | df46b33 | 2009-05-08 11:21:25 -0700 | [diff] [blame] | 748 | to interfaces describing simple method sets like this. |
Rob Pike | 6aabf31 | 2009-02-04 15:13:07 -0800 | [diff] [blame] | 749 | |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 750 | One last wrinkle. To complete the suite, besides "Printf" etc. and "Sprintf" |
| 751 | etc., there are also "Fprintf" etc. Unlike in C, "Fprintf"'s first argument is |
Rob Pike | df46b33 | 2009-05-08 11:21:25 -0700 | [diff] [blame] | 752 | not a file. Instead, it is a variable of type "io.Writer", which is an |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 753 | interface type defined in the "io" library: |
| 754 | |
Rob Pike | df46b33 | 2009-05-08 11:21:25 -0700 | [diff] [blame] | 755 | type Writer interface { |
Andrew Gerrand | a823496 | 2010-04-28 10:50:44 +1000 | [diff] [blame] | 756 | Write(p []byte) (n int, err os.Error) |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 757 | } |
| 758 | |
Rob Pike | df46b33 | 2009-05-08 11:21:25 -0700 | [diff] [blame] | 759 | (This interface is another conventional name, this time for "Write"; there are also |
| 760 | "io.Reader", "io.ReadWriter", and so on.) |
Rob Pike | 46f482a | 2011-05-25 06:44:09 +1000 | [diff] [blame] | 761 | Thus you can call "Fprintf" on any type that implements a standard "Write" |
Rob Pike | 83f0b71 | 2009-11-01 20:47:03 -0800 | [diff] [blame] | 762 | method, not just files but also network channels, buffers, whatever |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 763 | you want. |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 764 | |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 765 | Prime numbers |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 766 | ---- |
| 767 | |
Ian Lance Taylor | 97a55a7 | 2009-11-08 21:00:45 -0800 | [diff] [blame] | 768 | Now we come to processes and communication—concurrent programming. |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 769 | It's a big subject so to be brief we assume some familiarity with the topic. |
| 770 | |
Rob Pike | 83f0b71 | 2009-11-01 20:47:03 -0800 | [diff] [blame] | 771 | A classic program in the style is a prime sieve. |
Ian Lance Taylor | 97a55a7 | 2009-11-08 21:00:45 -0800 | [diff] [blame] | 772 | (The sieve of Eratosthenes is computationally more efficient than |
Rob Pike | 83f0b71 | 2009-11-01 20:47:03 -0800 | [diff] [blame] | 773 | the algorithm presented here, but we are more interested in concurrency than |
| 774 | algorithmics at the moment.) |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 775 | It works by taking a stream of all the natural numbers and introducing |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 776 | a sequence of filters, one for each prime, to winnow the multiples of |
| 777 | that prime. At each step we have a sequence of filters of the primes |
| 778 | so far, and the next number to pop out is the next prime, which triggers |
| 779 | the creation of the next filter in the chain. |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 780 | |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 781 | Here's a flow diagram; each box represents a filter element whose |
| 782 | creation is triggered by the first number that flowed from the |
| 783 | elements before it. |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 784 | |
| 785 | <br> |
| 786 | |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 787 | <img src='sieve.gif'> |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 788 | |
| 789 | <br> |
| 790 | |
| 791 | To create a stream of integers, we use a Go <i>channel</i>, which, |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 792 | borrowing from CSP's descendants, represents a communications |
| 793 | channel that can connect two concurrent computations. |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 794 | In Go, channel variables are references to a run-time object that |
| 795 | coordinates the communication; as with maps and slices, use |
| 796 | "make" to create a new channel. |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 797 | |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 798 | Here is the first function in "progs/sieve.go": |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 799 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 800 | !src progs/sieve.go /Send/ /^}/ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 801 | |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 802 | The "generate" function sends the sequence 2, 3, 4, 5, ... to its |
Ian Lance Taylor | 128f052 | 2008-09-22 11:29:40 -0700 | [diff] [blame] | 803 | argument channel, "ch", using the binary communications operator "<-". |
Rob Pike | 6aabf31 | 2009-02-04 15:13:07 -0800 | [diff] [blame] | 804 | Channel operations block, so if there's no recipient for the value on "ch", |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 805 | the send operation will wait until one becomes available. |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 806 | |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 807 | The "filter" function has three arguments: an input channel, an output |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 808 | channel, and a prime number. It copies values from the input to the |
Rob Pike | 592d2e3 | 2008-09-16 19:40:38 -0700 | [diff] [blame] | 809 | output, discarding anything divisible by the prime. The unary communications |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 810 | operator "<-" (receive) retrieves the next value on the channel. |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 811 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 812 | !src progs/sieve.go /Copy.the/ /^}/ |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 813 | |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 814 | The generator and filters execute concurrently. Go has |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 815 | its own model of process/threads/light-weight processes/coroutines, |
Ian Lance Taylor | 97a55a7 | 2009-11-08 21:00:45 -0800 | [diff] [blame] | 816 | so to avoid notational confusion we call concurrently executing |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 817 | computations in Go <i>goroutines</i>. To start a goroutine, |
| 818 | invoke the function, prefixing the call with the keyword "go"; |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 819 | this starts the function running in parallel with the current |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 820 | computation but in the same address space: |
| 821 | |
Andrew Gerrand | a823496 | 2010-04-28 10:50:44 +1000 | [diff] [blame] | 822 | go sum(hugeArray) // calculate sum in the background |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 823 | |
| 824 | If you want to know when the calculation is done, pass a channel |
| 825 | on which it can report back: |
| 826 | |
Andrew Gerrand | a823496 | 2010-04-28 10:50:44 +1000 | [diff] [blame] | 827 | ch := make(chan int) |
| 828 | go sum(hugeArray, ch) |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 829 | // ... do something else for a while |
Andrew Gerrand | a823496 | 2010-04-28 10:50:44 +1000 | [diff] [blame] | 830 | result := <-ch // wait for, and retrieve, result |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 831 | |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 832 | Back to our prime sieve. Here's how the sieve pipeline is stitched |
| 833 | together: |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 834 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 835 | !src progs/sieve.go /func.main/ /^}/ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 836 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 837 | The first line of "main" creates the initial channel to pass to "generate", which it |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 838 | then starts up. As each prime pops out of the channel, a new "filter" |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 839 | is added to the pipeline and <i>its</i> output becomes the new value |
| 840 | of "ch". |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 841 | |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 842 | The sieve program can be tweaked to use a pattern common |
| 843 | in this style of programming. Here is a variant version |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 844 | of "generate", from "progs/sieve1.go": |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 845 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 846 | !src progs/sieve1.go /func.generate/ /^}/ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 847 | |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 848 | This version does all the setup internally. It creates the output |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 849 | channel, launches a goroutine running a function literal, and |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 850 | returns the channel to the caller. It is a factory for concurrent |
| 851 | execution, starting the goroutine and returning its connection. |
Rob Pike | 6aabf31 | 2009-02-04 15:13:07 -0800 | [diff] [blame] | 852 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 853 | The function literal notation used in the "go" statement allows us to construct an |
Rob Pike | 6102877 | 2009-08-13 08:54:26 -0700 | [diff] [blame] | 854 | anonymous function and invoke it on the spot. Notice that the local |
| 855 | variable "ch" is available to the function literal and lives on even |
| 856 | after "generate" returns. |
Rob Pike | 6aabf31 | 2009-02-04 15:13:07 -0800 | [diff] [blame] | 857 | |
| 858 | The same change can be made to "filter": |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 859 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 860 | !src progs/sieve1.go /func.filter/ /^}/ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 861 | |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 862 | The "sieve" function's main loop becomes simpler and clearer as a |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 863 | result, and while we're at it let's turn it into a factory too: |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 864 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 865 | !src progs/sieve1.go /func.sieve/ /^}/ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 866 | |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 867 | Now "main"'s interface to the prime sieve is a channel of primes: |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 868 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 869 | !src progs/sieve1.go /func.main/ /^}/ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 870 | |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 871 | Multiplexing |
Rob Pike | db9002f | 2008-09-16 11:00:11 -0700 | [diff] [blame] | 872 | ---- |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 873 | |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 874 | With channels, it's possible to serve multiple independent client goroutines without |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 875 | writing an explicit multiplexer. The trick is to send the server a channel in the message, |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 876 | which it will then use to reply to the original sender. |
| 877 | A realistic client-server program is a lot of code, so here is a very simple substitute |
Rob Pike | 96777ea | 2009-01-30 10:18:58 -0800 | [diff] [blame] | 878 | to illustrate the idea. It starts by defining a "request" type, which embeds a channel |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 879 | that will be used for the reply. |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 880 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 881 | !src progs/server.go /type.request/ /^}/ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 882 | |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 883 | The server will be trivial: it will do simple binary operations on integers. Here's the |
| 884 | code that invokes the operation and responds to the request: |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 885 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 886 | !src progs/server.go /type.binOp/ /^}/ |
Rob Pike | a43033a | 2008-09-15 11:48:37 -0700 | [diff] [blame] | 887 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 888 | The type declaration makes "binOp" represent a function taking two integers and |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 889 | returning a third. |
| 890 | |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 891 | The "server" routine loops forever, receiving requests and, to avoid blocking due to |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 892 | a long-running operation, starting a goroutine to do the actual work. |
| 893 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 894 | !src progs/server.go /func.server/ /^}/ |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 895 | |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 896 | We construct a server in a familiar way, starting it and returning a channel |
| 897 | connected to it: |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 898 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 899 | !src progs/server.go /func.startServer/ /^}/ |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 900 | |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 901 | Here's a simple test. It starts a server with an addition operator and sends out |
| 902 | "N" requests without waiting for the replies. Only after all the requests are sent |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 903 | does it check the results. |
| 904 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 905 | !src progs/server.go /func.main/ /^}/ |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 906 | |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 907 | One annoyance with this program is that it doesn't shut down the server cleanly; when "main" returns |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 908 | there are a number of lingering goroutines blocked on communication. To solve this, |
Rob Pike | 40d5435 | 2009-01-09 15:16:31 -0800 | [diff] [blame] | 909 | we can provide a second, "quit" channel to the server: |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 910 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 911 | !src progs/server1.go /func.startServer/ /^}/ |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 912 | |
Rob Pike | ae05f00 | 2009-01-20 19:32:36 -0800 | [diff] [blame] | 913 | It passes the quit channel to the "server" function, which uses it like this: |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 914 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 915 | !src progs/server1.go /func.server/ /^}/ |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 916 | |
Russ Cox | 898714a | 2009-11-07 18:05:30 -0800 | [diff] [blame] | 917 | Inside "server", the "select" statement chooses which of the multiple communications |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 918 | listed by its cases can proceed. If all are blocked, it waits until one can proceed; if |
| 919 | multiple can proceed, it chooses one at random. In this instance, the "select" allows |
| 920 | the server to honor requests until it receives a quit message, at which point it |
Rob Pike | 592d2e3 | 2008-09-16 19:40:38 -0700 | [diff] [blame] | 921 | returns, terminating its execution. |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 922 | |
| 923 | |
| 924 | All that's left is to strobe the "quit" channel |
| 925 | at the end of main: |
| 926 | |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 927 | !src progs/server1.go /adder,.quit/ |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 928 | ... |
Rob Pike | 9cf37c3 | 2011-07-04 16:15:14 +1000 | [diff] [blame] | 929 | !src progs/server1.go /quit....true/ |
Rob Pike | 6820196 | 2008-09-16 13:14:44 -0700 | [diff] [blame] | 930 | |
| 931 | There's a lot more to Go programming and concurrent programming in general but this |
| 932 | quick tour should give you some of the basics. |