| <!DOCTYPE html> |
| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html;charset=utf-8" > |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> |
| <title>A Tour of Go</title> |
| |
| <!-- jQuery --> |
| <script src="static/jquery.js"></script> |
| |
| <!-- CodeMirror --> |
| <link rel="stylesheet" href="/static/codemirror/lib/codemirror.css"> |
| <script src="/static/codemirror/lib/codemirror.js"></script> |
| <script src="/static/codemirror/lib/go.js"></script> |
| |
| <!-- Tour --> |
| <link rel="stylesheet" href="static/tour.css"> |
| <script src="static/mode.js"></script> |
| <script src="static/tour.js"></script> |
| |
| </head> |
| <body> |
| <div id="wrap"> |
| <div id="header"> |
| <div id="slidenum">1</div> |
| <a href="#toc" id="tocbtn" title="Table of Contents"></a> |
| <h1>A Tour of Go</h1> |
| </div> |
| |
| <div id="slides" class="slides"><!-- begin slides --> |
| |
| <div class="slide"> |
| <h2>Hello, 世界</h2> |
| <p> |
| Welcome to a tour of the |
| <a target="_blank" href="http://golang.org/">Go programming language</a>. |
| <p> |
| The tour is divided into three sections. At the end of each section |
| is a series of exercises for you to complete. |
| <p> |
| The tour is interactive. Click the Run button now (or type |
| Shift-Enter) to compile and run the program on |
| <span class="appengineMode">a remote server.</span> |
| <span class="localMode">your computer.</span> |
| The result is displayed below the code. |
| <p> |
| These example programs demonstrate different aspects of Go. The |
| programs in the tour are meant to be starting points for your own |
| experimentation. |
| <p> |
| Edit the program and run it again. |
| <p> |
| Whenever you're ready to move on, click the Next button or type the |
| PageDown key. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func main() { |
| fmt.Println("Hello, 世界") |
| }</pre> |
| </div> |
| |
| <div class="slide nocode appengineMode"> |
| <h2>Go local</h2> |
| <p> |
| The tour is available in other languages: |
| <ul> |
| <li><a href="http://go-tour-br.appspot.com/">Brazilian Portuguese — Português do Brasil</a></li> |
| <li><a href="http://go-tour-zh.appspot.com/">Chinese — 普通话</a></li> |
| <li><a href="http://go-tour-jp.appspot.com/">Japanese — 日本語</a></li> |
| </ul> |
| <p> |
| (If you would like to translate the tour to another language, check |
| out the source from <code>https://code.google.com/p/go-tour</code>, |
| translate <code>static/index.html</code>, and then deploy it to App |
| Engine using the instructions in <code>appengine/README</code>.) |
| <p> |
| Click the "next" button or type PageDown to continue. |
| </div> |
| |
| <div class="slide nocode appengineMode"> |
| <h2>Go offline</h2> |
| <p> |
| This tour is also available as a stand-alone program that you can use |
| without access to the internet. |
| <p> |
| The stand-alone tour is faster, as it builds and runs the code samples |
| on your own machine. It also includes additional exercises not |
| available in this sandboxed version. |
| <p> |
| To run the tour locally first |
| <a target="_blank" href="http://golang.org/doc/install/">install Go</a>, |
| then use |
| <a target="_blank" href="http://golang.org/cmd/go/">go get</a> to install |
| <a target="_blank" href="http://code.google.com/p/go-tour/">gotour</a>: |
| <pre>go get code.google.com/p/go-tour/gotour</pre> |
| <p> |
| and run the resultant <code>gotour</code> executable. |
| <p> |
| Otherwise, click the "next" button or type PageDown to continue. |
| <p> |
| <i>(You may return to these instructions at any time by clicking the |
| "index" button.)</i> |
| </div> |
| |
| <div class="toc">Introduction</div> |
| |
| <div class="slide"> |
| <h2>Packages</h2> |
| <p> |
| Every Go program is made up of packages. |
| <p> |
| Programs start running in package <code>main</code>. |
| <p> |
| This program is using the packages with import paths |
| <code>"fmt"</code> and <code>"math"</code>. |
| <p> |
| By convention, the package name is the same as the |
| last element of the import path. |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "math" |
| ) |
| |
| func main() { |
| fmt.Println("Happy", math.Pi, "Day") |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Imports</h2> |
| <p> |
| This code groups the imports into a parenthesized, "factored" import |
| statement. You can also write multiple import statements, like: |
| <pre>import "fmt" |
| import "math"</pre> |
| but it's common to use the factored form to eliminate clutter. |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "math" |
| ) |
| |
| func main() { |
| fmt.Printf("Now you have %g problems.", |
| math.Nextafter(2, 3)) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Exported names</h2> |
| <p> |
| After importing a package, you can refer to the names it exports. |
| <p> |
| In Go, a name is exported if it begins with a capital letter. |
| <p> |
| <code>Foo</code> is an exported name, as is <code>FOO</code>. |
| The name <code>foo</code> is not exported. |
| <p> |
| Run the code. Then rename <code>math.pi</code> to <code>math.Pi</code> |
| and try it again. |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "math" |
| ) |
| |
| func main() { |
| fmt.Println(math.pi) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Functions</h2> |
| <p> |
| A function can take zero or more arguments. |
| <p> |
| In this example, <code>add</code> takes two parameters of type <code>int</code>. |
| <p> |
| Notice that the type comes <i>after</i> the variable name. |
| <p> |
| (For more about why types look the way they do, see the <a target="_blank" href="http://golang.org/doc/articles/gos_declaration_syntax.html">article on Go's declaration syntax</a>.) |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func add(x int, y int) int { |
| return x + y |
| } |
| |
| func main() { |
| fmt.Println(add(42, 13)) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Functions</h2> |
| <p> |
| When two or more consecutive named function parameters share a type, |
| you can omit the type from all but the last. |
| <p> |
| In this example, we shortened |
| <pre>x int, y int</pre> |
| <p> |
| to |
| <pre>x, y int</pre> |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func add(x, y int) int { |
| return x + y |
| } |
| |
| func main() { |
| fmt.Println(add(42, 13)) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Functions</h2> |
| <p> |
| A function can return any number of results. |
| <p> |
| This function returns two strings. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func swap(x, y string) (string, string) { |
| return y, x |
| } |
| |
| func main() { |
| a, b := swap("hello", "world") |
| fmt.Println(a, b) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Functions</h2> |
| <p> |
| Functions take parameters. In Go, functions can return multiple |
| "result parameters", not just a single value. They can be named and act |
| just like variables. |
| <p> |
| If the result parameters are named, a <code>return</code> statement |
| without arguments returns the current values of the results. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func split(sum int) (x, y int) { |
| x = sum * 4/9 |
| y = sum - x |
| return |
| } |
| |
| func main() { |
| fmt.Println(split(17)) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Variables</h2> |
| <p> |
| The <code>var</code> statement declares a list of variables; |
| as in function argument lists, the type is last. |
| |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| var x, y, z int |
| var c, python, java bool |
| |
| func main() { |
| fmt.Println(x, y, z, c, python, java) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Variables</h2> |
| <p> |
| A var declaration can include initializers, one per variable. |
| <p> |
| If an initializer is present, the type can be omitted; |
| the variable will take the type of the initializer. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| var x, y, z int = 1, 2, 3 |
| var c, python, java = true, false, "no!" |
| |
| func main() { |
| fmt.Println(x, y, z, c, python, java) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Variables</h2> |
| <p> |
| Inside a function, the <code>:=</code> short assignment statement can |
| be used in place of a <code>var</code> declaration with implicit type. |
| <p> |
| (Outside a function, every construct begins with a keyword and the |
| <code>:=</code> construct is not available.) |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func main() { |
| var x, y, z int = 1, 2, 3 |
| c, python, java := true, false, "no!" |
| |
| fmt.Println(x, y, z, c, python, java) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Constants</h2> |
| <p> |
| Constants are declared like variables, but with the <code>const</code> |
| keyword. |
| <p> |
| Constants can be character, string, boolean, or numeric values. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| const Pi = 3.14 |
| |
| func main() { |
| const World = "世界" |
| fmt.Println("Hello", World) |
| fmt.Println("Happy", Pi, "Day") |
| |
| const Truth = true |
| fmt.Println("Go rules?", Truth) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Numeric Constants</h2> |
| <p> |
| Numeric constants are high-precision <i>values</i>. |
| <p> |
| An untyped constant takes the type needed by its context. |
| <p> |
| Try printing <code>needInt(Big)</code> too. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| const ( |
| Big = 1<<100 |
| Small = Big>>99 |
| ) |
| |
| func needInt(x int) int { return x*10 + 1 } |
| func needFloat(x float64) float64 { |
| return x*0.1 |
| } |
| |
| func main() { |
| fmt.Println(needInt(Small)) |
| fmt.Println(needFloat(Small)) |
| fmt.Println(needFloat(Big)) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>For</h2> |
| <p> |
| Go has only one looping construct, the <code>for</code> loop. |
| <p> |
| The basic <code>for</code> loop looks as it does in C or Java, |
| except that the <code>( )</code> are gone (they are not even optional) |
| and the <code>{ }</code> are required. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func main() { |
| sum := 0 |
| for i := 0; i < 10; i++ { |
| sum += i |
| } |
| fmt.Println(sum) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>For</h2> |
| <p> |
| As in C or Java, you can leave the pre and post statements empty. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func main() { |
| sum := 1 |
| for ; sum < 1000; { |
| sum += sum |
| } |
| fmt.Println(sum) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>For</h2> |
| <p> |
| At that point you can drop the semicolons: |
| C's <code>while</code> is spelled <code>for</code> in Go. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func main() { |
| sum := 1 |
| for sum < 1000 { |
| sum += sum |
| } |
| fmt.Println(sum) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>For</h2> |
| <p> |
| If you omit the loop condition, it loops forever. |
| <pre class="source">package main |
| |
| func main() { |
| for ; ; { |
| } |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>For</h2> |
| <p> |
| And with no clauses at all, the semicolons can be omitted, |
| so an infinite loop is compactly expressed. |
| <pre class="source">package main |
| |
| func main() { |
| for { |
| } |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>If</h2> |
| <p> |
| The <code>if</code> statement looks as it does in C or Java, |
| except that the <code>( )</code> are gone (they are not even optional) |
| and the <code>{ }</code> are required. |
| <p> |
| (Sound familiar?) |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "math" |
| ) |
| |
| func sqrt(x float64) string { |
| if x < 0 { |
| return sqrt(-x) + "i" |
| } |
| return fmt.Sprint(math.Sqrt(x)) |
| } |
| |
| func main() { |
| fmt.Println(sqrt(2), sqrt(-4)) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>If</h2> |
| <p> |
| Like <code>for</code>, the <code>if</code> statement can start with a |
| short statement to execute before the condition. |
| <p> |
| Variables declared by the statement are only in scope until the end of |
| the <code>if</code>. |
| <p> |
| (Try using <code>v</code> in the last <code>return</code> statement.) |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "math" |
| ) |
| |
| func pow(x, n, lim float64) float64 { |
| if v := math.Pow(x, n); v < lim { |
| return v |
| } |
| return lim |
| } |
| |
| func main() { |
| fmt.Println( |
| pow(3, 2, 10), |
| pow(3, 3, 20), |
| ) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>If</h2> |
| <p> |
| Variables declared inside an <code>if</code>'s short statement are also |
| available inside any of the <code>else</code> blocks. |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "math" |
| ) |
| |
| func pow(x, n, lim float64) float64 { |
| if v := math.Pow(x, n); v < lim { |
| return v |
| } else { |
| fmt.Printf("%g >= %g\n", v, lim) |
| } |
| // can't use v here, though |
| return lim |
| } |
| |
| func main() { |
| fmt.Println( |
| pow(3, 2, 10), |
| pow(3, 3, 20), |
| ) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Basic types</h2> |
| <p> |
| Go's basic types are |
| <pre>bool |
| |
| string |
| |
| int int8 int16 int32 int64 |
| uint uint8 uint16 uint32 uint64 uintptr |
| |
| byte // alias for uint8 |
| |
| rune // alias for int32 |
| // represents a Unicode code point |
| |
| float32 float64 |
| |
| complex64 complex128</pre> |
| <pre class="source">package main |
| |
| import ( |
| "math/cmplx" |
| "fmt" |
| ) |
| |
| var ( |
| ToBe bool = false |
| MaxInt uint64 = 1<<64 - 1 |
| z complex128 = cmplx.Sqrt(-5+12i) |
| ) |
| |
| func main() { |
| const f = "%T(%v)\n" |
| fmt.Printf(f, ToBe, ToBe) |
| fmt.Printf(f, MaxInt, MaxInt) |
| fmt.Printf(f, z, z) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Structs</h2> |
| <p> |
| A <code>struct</code> is a collection of fields. |
| <p> |
| (And a <code>type</code> declaration does what you'd expect.) |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| type Vertex struct { |
| X int |
| Y int |
| } |
| |
| func main() { |
| fmt.Println(Vertex{1, 2}) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Struct Fields</h2> |
| <p> |
| Struct fields are accessed using a dot. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| type Vertex struct { |
| X int |
| Y int |
| } |
| |
| func main() { |
| v := Vertex{1, 2} |
| v.X = 4 |
| fmt.Println(v.X) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Pointers</h2> |
| <p> |
| Go has pointers, but no pointer arithmetic. |
| <p> |
| Struct fields can be accessed through a struct pointer. |
| The indirection through the pointer is transparent. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| type Vertex struct { |
| X int |
| Y int |
| } |
| |
| func main() { |
| p := Vertex{1, 2} |
| q := &p |
| q.X = 1e9 |
| fmt.Println(p) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Struct Literals</h2> |
| <p> |
| A struct literal denotes a newly allocated struct value by listing the |
| values of its fields. |
| <p> |
| You can list just a subset of fields by using the <code>Name:</code> |
| syntax. (And the order of named fields is irrelevant.) |
| <p> |
| The special prefix <code>&</code> constructs a pointer to a struct |
| literal. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| type Vertex struct { |
| X, Y int |
| } |
| |
| var ( |
| p = Vertex{1, 2} // has type Vertex |
| q = &Vertex{1, 2} // has type *Vertex |
| r = Vertex{X: 1} // Y:0 is implicit |
| s = Vertex{} // X:0 and Y:0 |
| ) |
| |
| func main() { |
| fmt.Println(p, q, r, s) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>The new function</h2> |
| <p> |
| The expression <code>new(T)</code> allocates a zeroed <code>T</code> |
| value and returns a pointer to it. |
| <pre>var t *T = new(T)</pre> |
| <p> |
| or |
| <pre>t := new(T)</pre> |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| type Vertex struct { |
| X, Y int |
| } |
| |
| func main() { |
| v := new(Vertex) |
| fmt.Println(v) |
| v.X, v.Y = 11, 9 |
| fmt.Println(v) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Maps</h2> |
| <p> |
| A map maps keys to values. |
| <p> |
| <!-- TODO: empty part not true in compilers yet --> |
| Maps must be created with <code>make</code> (not <code>new</code>) |
| before use; the <code>nil</code> map is empty and cannot be assigned |
| to. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| type Vertex struct { |
| Lat, Long float64 |
| } |
| |
| var m map[string]Vertex |
| |
| func main() { |
| m = make(map[string]Vertex) |
| m["Bell Labs"] = Vertex{ |
| 40.68433, 74.39967, |
| } |
| fmt.Println(m["Bell Labs"]) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Maps</h2> |
| <p> |
| Map literals are like struct literals, but the keys are required. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| type Vertex struct { |
| Lat, Long float64 |
| } |
| |
| var m = map[string]Vertex{ |
| "Bell Labs": Vertex{ |
| 40.68433, -74.39967, |
| }, |
| "Google": Vertex{ |
| 37.42202, -122.08408, |
| }, |
| } |
| |
| func main() { |
| fmt.Println(m) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Maps</h2> |
| <p> |
| If the top-level type is just a type name, you can omit it from the |
| elements of the literal. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| type Vertex struct { |
| Lat, Long float64 |
| } |
| |
| var m = map[string]Vertex{ |
| "Bell Labs": {40.68433, -74.39967}, |
| "Google": {37.42202, -122.08408}, |
| } |
| |
| func main() { |
| fmt.Println(m) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Mutating Maps</h2> |
| <p> |
| Insert or update an element in map <code>m</code>: |
| <pre>m[key] = elem</pre> |
| <p> |
| Retrieve an element: |
| <pre>elem = m[key]</pre> |
| <p> |
| Delete an element: |
| <pre>delete(m, key)</pre> |
| <p> |
| Test that a key is present with a two-value assignment: |
| <pre>elem, ok = m[key]</pre> |
| <p> |
| If <code>key</code> is in <code>m</code>, |
| <code>ok</code> is <code>true</code>. |
| If not, <code>ok</code> is <code>false</code> and |
| <code>elem</code> is the zero value for the map's element type. |
| <p> |
| Similarly, when reading from a map if the key is not present |
| the result is the zero value for the map's element type. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func main() { |
| m := make(map[string]int) |
| |
| m["Answer"] = 42 |
| fmt.Println("The value:", m["Answer"]) |
| |
| m["Answer"] = 48 |
| fmt.Println("The value:", m["Answer"]) |
| |
| delete(m, "Answer") |
| fmt.Println("The value:", m["Answer"]) |
| |
| v, ok := m["Answer"] |
| fmt.Println("The value:", v, "Present?", ok) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Slices</h2> |
| <p> |
| A slice points to an array of values and also includes a length. |
| <p> |
| <code>[]T</code> is a slice with elements of type <code>T</code>. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func main() { |
| p := []int{2, 3, 5, 7, 11, 13} |
| fmt.Println("p ==", p) |
| |
| for i := 0; i < len(p); i++ { |
| fmt.Printf("p[%d] == %d\n", |
| i, p[i]) |
| } |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Slices</h2> |
| <p> |
| Slices can be re-sliced, creating a new slice value that points to the |
| same array. |
| <p> |
| The expression |
| <pre>s[lo:hi]</pre> |
| <p> |
| evaluates to a slice of the elements from <code>lo</code> through |
| <code>hi-1</code>, inclusive. Thus |
| <pre>s[lo:lo]</pre> |
| <p> |
| is empty and |
| <pre>s[lo:lo+1]</pre> |
| <p> |
| has one element. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func main() { |
| p := []int{2, 3, 5, 7, 11, 13} |
| fmt.Println("p ==", p) |
| fmt.Println("p[1:4] ==", p[1:4]) |
| |
| // missing low index implies 0 |
| fmt.Println("p[:3] ==", p[:3]) |
| |
| // missing high index implies len(s) |
| fmt.Println("p[4:] ==", p[4:]) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Slices</h2> |
| <p> |
| Slices are created with the <code>make</code> function. It works by |
| allocating a zeroed array and returning a slice that refers to that |
| array: |
| <pre>a := make([]int, 5) // len(a)=5</pre> |
| Slices have length and capacity. A slice's capacity is the maximum |
| length the slice can grow within the underlying array. |
| <p> |
| To specify a capacity, pass a third argument to <code>make</code>: |
| <p> |
| <pre>b := make([]int, 0, 5) // len(b)=0, cap(b)=5</pre> |
| Slices can be grown by "re-slicing" (up to their capacity): |
| <p> |
| <pre>b = b[:cap(b)] // len(b)=5, cap(b)=5 |
| b = b[1:] // len(b)=4, cap(b)=4</pre> |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func main() { |
| a := make([]int, 5) |
| printSlice("a", a) |
| b := make([]int, 0, 5) |
| printSlice("b", b) |
| c := b[:2] |
| printSlice("c", c) |
| d := c[2:5] |
| printSlice("d", d) |
| } |
| |
| func printSlice(s string, x []int) { |
| fmt.Printf("%s len=%d cap=%d %v\n", |
| s, len(x), cap(x), x) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Slices</h2> |
| <p> |
| The zero value of a slice is <code>nil</code>. |
| <p> |
| A nil slice has a length and capacity of 0. |
| <p> |
| (To learn more about slices, read the |
| "<a target="_blank" href="http://golang.org/doc/articles/slices_usage_and_internals.html">Slices: usage and internals</a>" |
| article.) |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func main() { |
| var z []int |
| fmt.Println(z, len(z), cap(z)) |
| if z == nil { |
| fmt.Println("nil!") |
| } |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Functions</h2> |
| <p> |
| Functions are values too. |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "math" |
| ) |
| |
| func main() { |
| hypot := func(x, y float64) float64 { |
| return math.Sqrt(x*x + y*y) |
| } |
| |
| fmt.Println(hypot(3, 4)) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Functions</h2> |
| <p> |
| And functions are full closures. |
| <p> |
| The <code>adder</code> function returns a closure. |
| Each closure is bound to its own <code>sum</code> variable. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func adder() func(int) int { |
| sum := 0 |
| return func(x int) int { |
| sum += x |
| return sum |
| } |
| } |
| |
| func main() { |
| pos, neg := adder(), adder() |
| for i := 0; i < 10; i++ { |
| fmt.Println( |
| pos(i), |
| neg(-2*i), |
| ) |
| } |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Range</h2> |
| <p> |
| The <code>range</code> form of the <code>for</code> |
| loop iterates over a slice or map. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| var pow = []int{1, 2, 4, 8, 16, 32, 64, 128} |
| |
| func main() { |
| for i, v := range pow { |
| fmt.Printf("2**%d = %d\n", i, v) |
| } |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Range</h2> |
| <p> |
| You can skip the index or value by assigning to <code>_</code>. |
| <p> |
| If you only want the index, drop the |
| “<code>, value</code>” entirely. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func main() { |
| pow := make([]int, 10) |
| for i := range pow { |
| pow[i] = 1<<uint(i) |
| } |
| for _, value := range pow { |
| fmt.Printf("%d\n", value) |
| } |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Switch</h2> |
| <p> |
| You probably knew what <code>switch</code> was going to look like. |
| <p> |
| A case body breaks automatically, unless it ends with a <code>fallthrough</code> statement. |
| |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "runtime" |
| ) |
| |
| func main() { |
| fmt.Print("Go runs on ") |
| switch os := runtime.GOOS; os { |
| case "darwin": |
| fmt.Println("OS X.") |
| case "linux": |
| fmt.Println("Linux.") |
| default: |
| // freebsd, openbsd, |
| // plan9, windows... |
| fmt.Printf("%s.", os) |
| } |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Switch</h2> |
| <p> |
| Switch cases evaluate cases from top to bottom, stopping when a |
| case succeeds. |
| <p> |
| (For example, |
| <pre>switch i { |
| case 0: |
| case f(): |
| }</pre> |
| <p> |
| does not call <code>f</code> if <code>i==0</code>.) |
| |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "time" |
| ) |
| |
| func main() { |
| fmt.Println("When's Saturday?") |
| today := time.Now().Weekday() |
| switch time.Saturday { |
| case today+0: |
| fmt.Println("Today.") |
| case today+1: |
| fmt.Println("Tomorrow.") |
| case today+2: |
| fmt.Println("In two days.") |
| default: |
| fmt.Println("Too far away.") |
| } |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Switch</h2> |
| <p> |
| Switch without a condition is the same as <code>switch true</code>. |
| <p> |
| This construct can be a clean way to write long if-then-else chains. |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "time" |
| ) |
| |
| func main() { |
| t := time.Now() |
| switch { |
| case t.Hour() < 12: |
| fmt.Println("Good morning!") |
| case t.Hour() < 17: |
| fmt.Println("Good afternoon.") |
| default: |
| fmt.Println("Good evening.") |
| } |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Exercise: Loops and Functions</h2> |
| <p> |
| As a simple way to play with functions and loops, implement |
| the square root function using Newton's method. |
| <p> |
| In this case, Newton's method is to approximate <code>Sqrt(x)</code> |
| by picking a starting point <i>z</i> and then repeating: |
| <div style="text-align: center"> |
| <img src="https://chart.googleapis.com/chart?cht=tx&chl=z=z-\frac{z^2-x}{2z}" alt="Newton's method"> |
| </div> |
| <p> |
| To begin with, just repeat that calculation 10 times and see how close you |
| get to the answer for various values (1, 2, 3, ...). |
| <p> |
| Next, change the loop condition to stop once the value has stopped |
| changing (or only changes by a very small delta). |
| See if that's more or fewer iterations. |
| How close are you to the <a target="_blank" href="http://golang.org/pkg/math/#Sqrt">math.Sqrt</a>? |
| <p> |
| Hint: to declare and initialize a floating point value, give it |
| floating point syntax or use a conversion: |
| <pre>z := float64(1) |
| z := 1.0</pre> |
| |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| ) |
| |
| func Sqrt(x float64) float64 { |
| } |
| |
| func main() { |
| fmt.Println(Sqrt(2)) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Exercise: Maps</h2> |
| <p> |
| Implement <code>WordCount</code>. It should return a map of the |
| counts of each “word” in the string <code>s</code>. |
| The <code>wc.Test</code> function runs a test suite against the |
| provided function and prints success or failure. |
| <p> |
| You might find <a target="_blank" href="http://golang.org/pkg/strings/#Fields">strings.Fields</a> helpful. |
| |
| <pre class="source">package main |
| |
| import ( |
| "<span class="appengineMode">tour</span><span class="localMode">code.google.com/p/go-tour</span>/wc" |
| ) |
| |
| func WordCount(s string) map[string]int { |
| return map[string]int{"x": 1} |
| } |
| |
| func main() { |
| wc.Test(WordCount) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Exercise: Slices</h2> |
| <p> |
| Implement <code>Pic</code>. It should return a slice of length |
| <code>dy</code>, each element of which is a slice of <code>dx</code> |
| 8-bit unsigned integers. When you run the program, it will display |
| your picture, interpreting the integers as grayscale (well, bluescale) |
| values. |
| <p> |
| The choice of image is up to you. |
| Interesting functions include <code>x^y</code>, <code>(x+y)/2</code>, and <code>x*y</code>. |
| <p> |
| (You need to use a loop to allocate each <code>[]uint8</code> inside |
| the <code>[][]uint8</code>.) |
| <p> |
| (Use <code>uint8(intValue)</code> to convert between types.) |
| |
| <pre class="source">package main |
| |
| import "<span class="appengineMode">tour</span><span class="localMode">code.google.com/p/go-tour</span>/pic" |
| |
| func Pic(dx, dy int) [][]uint8 { |
| } |
| |
| func main() { |
| pic.Show(Pic) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Exercise: Fibonacci closure</h2> |
| <p> |
| Let's have some fun with functions. |
| <p> |
| Implement a <code>fibonacci</code> function that returns a function |
| (a closure) that returns successive fibonacci numbers. |
| |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| // fibonacci is a function that returns |
| // a function that returns an int. |
| func fibonacci() func() int { |
| } |
| |
| func main() { |
| f := fibonacci() |
| for i := 0; i < 10; i++ { |
| fmt.Println(f()) |
| } |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Advanced Exercise: Complex cube roots</h2> |
| <p> |
| Let's explore Go's built-in support for complex numbers via the |
| <code>complex64</code> and <code>complex128</code> types. |
| For cube roots, Newton's method amounts to repeating: |
| <div style="text-align: center"> |
| <img src="https://chart.googleapis.com/chart?cht=tx&chl=z=z-\frac{z^3-x}{3z^2}" alt="Newton's method"> |
| </div> |
| <p> |
| Find the cube root of 2, just to make sure the algorithm works. |
| There is a <a target="_blank" href="http://golang.org/pkg/math/cmplx/#Pow">Pow</a> |
| function in the <code>math/cmplx</code> package. |
| |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func Cbrt(x complex128) complex128 { |
| } |
| |
| func main() { |
| fmt.Println(Cbrt(2)) |
| }</pre> |
| </div> |
| |
| |
| <div class="toc">Methods and Interfaces</div> |
| |
| <div class="slide nocode"> |
| <h2>Methods and Interfaces</h2> |
| </div> |
| |
| <div class="slide"> |
| <h2>Methods</h2> |
| <p> |
| Go does not have classes. However, you can define methods on struct |
| types. |
| <p> |
| The <i>method receiver</i> appears in its own argument list |
| between the <code>func</code> keyword and the method name. |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "math" |
| ) |
| |
| type Vertex struct { |
| X, Y float64 |
| } |
| |
| func (v *Vertex) Abs() float64 { |
| return math.Sqrt(v.X*v.X + v.Y*v.Y) |
| } |
| |
| func main() { |
| v := &Vertex{3, 4} |
| fmt.Println(v.Abs()) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Methods</h2> |
| <p> |
| In fact, you can define a method on <i>any</i> type you define in your |
| package, not just structs. |
| <p> |
| You cannot define a method on a type from another package, or on a |
| basic type. |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "math" |
| ) |
| |
| type MyFloat float64 |
| |
| func (f MyFloat) Abs() float64 { |
| if f < 0 { |
| return float64(-f) |
| } |
| return float64(f) |
| } |
| |
| func main() { |
| f := MyFloat(-math.Sqrt2) |
| fmt.Println(f.Abs()) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Methods with pointer receivers</h2> |
| <p> |
| Methods can be associated with a named type or a pointer |
| to a named type. |
| <p> |
| We just saw two <code>Abs</code> methods. One on the |
| <code>*Vertex</code> pointer type and the other on the |
| <code>MyFloat</code> value type. |
| <p> |
| There are two reasons to use a pointer receiver. |
| First, to avoid copying the value on each method call (more efficient |
| if the value type is a large struct). Second, so that the method can |
| modify the value that its receiver points to. |
| <p> |
| Try changing the declarations of the <code>Abs</code> and |
| <code>Scale</code> methods to use <code>Vertex</code> as the |
| receiver, instead of <code>*Vertex</code>. |
| <p> |
| The <code>Scale</code> method has no effect when <code>v</code> is a |
| <code>Vertex</code>. <code>Scale</code> mutates <code>v</code>. When |
| <code>v</code> is a value (non-pointer) type, the method sees a copy of |
| the <code>Vertex</code> and cannot mutate the original value. |
| <p> |
| <code>Abs</code> works either way. It only reads <code>v</code>. |
| It doesn't matter whether it is reading the original value (through a |
| pointer) or a copy of that value. |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "math" |
| ) |
| |
| type Vertex struct { |
| X, Y float64 |
| } |
| |
| func (v *Vertex) Scale(f float64) { |
| v.X = v.X * f |
| v.Y = v.Y * f |
| } |
| |
| func (v *Vertex) Abs() float64 { |
| return math.Sqrt(v.X*v.X + v.Y*v.Y) |
| } |
| |
| func main() { |
| v := &Vertex{3, 4} |
| v.Scale(5) |
| fmt.Println(v, v.Abs()) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Interfaces</h2> |
| <p> |
| An interface type is defined by a set of methods. |
| <p> |
| A value of interface type can hold any value that |
| implements those methods. |
| |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "math" |
| ) |
| |
| type Abser interface { |
| Abs() float64 |
| } |
| |
| func main() { |
| var a Abser |
| f := MyFloat(-math.Sqrt2) |
| v := Vertex{3, 4} |
| |
| a = f // a MyFloat implements Abser |
| a = &v // a *Vertex implements Abser |
| a = v // a Vertex, does NOT |
| // implement Abser |
| |
| fmt.Println(a.Abs()) |
| } |
| |
| type MyFloat float64 |
| |
| func (f MyFloat) Abs() float64 { |
| if f < 0 { |
| return float64(-f) |
| } |
| return float64(f) |
| } |
| |
| type Vertex struct { |
| X, Y float64 |
| } |
| |
| func (v *Vertex) Abs() float64 { |
| return math.Sqrt(v.X*v.X + v.Y*v.Y) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Interfaces</h2> |
| <p> |
| A type implements an interface by implementing the methods. |
| <p> |
| <i>There is no explicit declaration of intent.</i> |
| <p> |
| Implicit interfaces decouple implementation packages from the packages |
| that define the interfaces: neither depends on the other. |
| <p> |
| It also encourages the definition of precise interfaces, because you |
| don't have to find every implementation and tag it with the new |
| interface name. |
| <p> |
| <a target="_blank" href="http://golang.org/pkg/io/">Package io</a> defines <code>Reader</code> and <code>Writer</code>; you don't have to. |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "os" |
| ) |
| |
| type Reader interface { |
| Read(b []byte) (n int, err error) |
| } |
| |
| type Writer interface { |
| Write(b []byte) (n int, err error) |
| } |
| |
| type ReadWriter interface { |
| Reader |
| Writer |
| } |
| |
| func main() { |
| var w Writer |
| |
| // os.Stdout implements Writer |
| w = os.Stdout |
| |
| fmt.Fprintf(w, "hello, writer\n") |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Errors</h2> |
| <p> |
| An error is anything that can describe itself as an error string. |
| The idea is captured by the predefined, built-in interface type, <code>error</code>, |
| with its single method, <code>Error</code>, returning a string: |
| <pre>type error interface { |
| Error() string |
| }</pre> |
| |
| <p> |
| The <code>fmt</code> package's various print routines automatically |
| know to call the method when asked to print an <code>error</code>. |
| |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "time" |
| ) |
| |
| type MyError struct { |
| When time.Time |
| What string |
| } |
| |
| func (e *MyError) Error() string { |
| return fmt.Sprintf("at %v, %s", |
| e.When, e.What) |
| } |
| |
| func run() error { |
| return &MyError{ |
| time.Now(), |
| "it didn't work", |
| } |
| } |
| |
| func main() { |
| if err := run(); err != nil { |
| fmt.Println(err) |
| } |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Web servers</h2> |
| <p> |
| <a target="_blank" href="http://golang.org/pkg/net/http/">Package http</a> serves HTTP requests using any value |
| that implements <code>http.Handler</code>: |
| <pre>package http |
| |
| type Handler interface { |
| ServeHTTP(w ResponseWriter, r *Request) |
| }</pre> |
| <p> |
| In this example, the type <code>Hello</code> implements <code>http.Handler</code>. |
| <p> |
| <span class="localMode"> |
| Visit <a href="http://localhost:4000/" target="_blank">http://localhost:4000/</a> to see the greeting. |
| </span> |
| <span class="appengineMode"> |
| <b>Note:</b> This example won't run through the web-based tour user |
| interface. To try writing web servers you may want to |
| <a target="_blank" href="http://golang.org/doc/install/">Install |
| Go</a>. |
| </span> |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "net/http" |
| ) |
| |
| type Hello struct{} |
| |
| func (h Hello) ServeHTTP( |
| w http.ResponseWriter, |
| r *http.Request) { |
| fmt.Fprint(w, "Hello!") |
| } |
| |
| func main() { |
| var h Hello |
| http.ListenAndServe("localhost:4000",h) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Images</h2> |
| <p> |
| <a target="_blank" href="http://golang.org/pkg/image/#Image">Package image</a> defines the <code>Image</code> |
| interface: |
| <pre>package image |
| |
| type Image interface { |
| ColorModel() color.Model |
| Bounds() Rectangle |
| At(x, y int) color.Color |
| }</pre> |
| <p> |
| (See <a target="_blank" href="http://golang.org/pkg/image/#Image">the |
| documentation</a> for all the details.) |
| <p> |
| Also, <code>color.Color</code> and <code>color.Model</code> are interfaces, |
| but we'll ignore that by using the predefined implementations |
| <code>color.RGBA</code> and <code>color.RGBAModel</code>. |
| |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "image" |
| ) |
| |
| func main() { |
| m := image.NewRGBA(image.Rect(0, 0, 100, 100)) |
| fmt.Println(m.Bounds()) |
| fmt.Println(m.At(0, 0).RGBA()) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Exercise: Errors</h2> |
| <p> |
| Copy your <code>Sqrt</code> function from the earlier exercises and |
| modify it to return an <code>error</code> value. |
| <p> |
| <code>Sqrt</code> should return a non-nil error value when given a |
| negative number, as it doesn't support complex numbers. |
| <p> |
| Create a new type |
| <pre>type ErrNegativeSqrt float64</pre> |
| <p> |
| and make it an <code>error</code> by giving it a |
| <pre>func (e ErrNegativeSqrt) Error() string</pre> |
| <p> |
| method such that <code>ErrNegativeSqrt(-2).Error()</code> returns |
| <code>"cannot Sqrt negative number: -2"</code>. |
| <p> |
| <b>Note:</b> a call to <code>fmt.Print(e)</code> inside the |
| <code>Error</code> method will send the program into an infinite loop. |
| You can avoid this by converting <code>e</code> first: |
| <code>fmt.Print(float64(e))</code>. Why? |
| <p> |
| Change your <code>Sqrt</code> function to return an |
| <code>ErrNegativeSqrt</code> value when given a negative number. |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| ) |
| |
| func Sqrt(f float64) (float64, error) { |
| return 0, nil |
| } |
| |
| func main() { |
| fmt.Println(Sqrt(2)) |
| fmt.Println(Sqrt(-2)) |
| }</pre> |
| </div> |
| |
| <div class="slide localMode"> |
| <h2>Exercise: HTTP Handlers</h2> |
| <p> |
| Implement the following types and define ServeHTTP methods on them. |
| Register them to handle specific paths in your web server. |
| <pre>type String string |
| |
| type Struct struct { |
| Greeting string |
| Punct string |
| Who string |
| }</pre> |
| <p> |
| For example, you should be able to register handlers using: |
| <pre>http.Handle("/string", String("I'm a frayed knot.")) |
| http.Handle("/struct", &Struct{"Hello", ":", "Gophers!"})</pre> |
| <pre class="source">package main |
| |
| import ( |
| "net/http" |
| ) |
| |
| func main() { |
| // your http.Handle calls here |
| http.ListenAndServe("localhost:4000", nil) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Exercise: Images</h2> |
| <p> |
| Remember the picture generator you wrote earlier? |
| Let's write another one, but this time it will return |
| an implementation of <code>image.Image</code> instead of a slice of data. |
| <p> |
| Define your own <code>Image</code> type, implement |
| <a href="http://golang.org/pkg/image/#Image" target="_blank">the necessary methods</a>, |
| and call <code>pic.ShowImage</code>. |
| <p> |
| <code>Bounds</code> should return a <code>image.Rectangle</code>, like |
| <code>image.Rect(0, 0, w, h)</code>. |
| <p> |
| <code>ColorModel</code> should return <code>color.RGBAModel</code>. |
| <p> |
| <code>At</code> should return a color; |
| the value <code>v</code> in the last picture generator corresponds to |
| <code>color.RGBA{v, v, 255, 255}</code> in this one. |
| |
| <pre class="source">package main |
| |
| import ( |
| "image" |
| "<span class="appengineMode">tour</span><span class="localMode">code.google.com/p/go-tour</span>/pic" |
| ) |
| |
| type Image struct{} |
| |
| func main() { |
| m := Image{} |
| pic.ShowImage(m) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Exercise: Rot13 Reader</h2> |
| <p> |
| A common pattern is an |
| <a target="_blank" href="http://golang.org/pkg/io/#Reader">io.Reader</a> that wraps |
| another <code>io.Reader</code>, modifying the stream in some way. |
| <p> |
| For example, the |
| <a target="_blank" href="http://golang.org/pkg/compress/gzip/#NewReader">gzip.NewReader</a> |
| function takes an <code>io.Reader</code> (a stream of gzipped data) |
| and returns a <code>*gzip.Reader</code> that also implements |
| <code>io.Reader</code> (a stream of the decompressed data). |
| <p> |
| Implement a <code>rot13Reader</code> that implements |
| <code>io.Reader</code> and reads from an <code>io.Reader</code>, |
| modifying the stream by applying the |
| <a target="_blank" href="http://en.wikipedia.org/wiki/ROT13">ROT13</a> |
| substitution cipher to all alphabetical characters. |
| <p> |
| The <code>rot13Reader</code> type is provided for you. Make it an |
| <code>io.Reader</code> by implementing its <code>Read</code> method. |
| <pre class="source">package main |
| |
| import ( |
| "io" |
| "os" |
| "strings" |
| ) |
| |
| type rot13Reader struct { |
| r io.Reader |
| } |
| |
| func main() { |
| s := strings.NewReader( |
| "Lbh penpxrq gur pbqr!") |
| r := rot13Reader{s} |
| io.Copy(os.Stdout, &r) |
| }</pre> |
| </div> |
| |
| <div class="toc">Concurrency</div> |
| |
| <div class="slide nocode"> |
| <h2>Concurrency</h2> |
| </div> |
| |
| <div class="slide"> |
| <h2>Goroutines</h2> |
| <p> |
| A <i>goroutine</i> is a lightweight thread managed by the Go runtime. |
| <pre>go f(x, y, z)</pre> |
| <p> |
| starts a new goroutine running |
| <pre>f(x, y, z)</pre> |
| <p> |
| The evaluation |
| of <code>f</code>, <code>x</code>, <code>y</code>, and <code>z</code> |
| happens in the current goroutine and the execution of <code>f</code> |
| happens in the new goroutine. |
| <p> |
| Goroutines run in the same address space, so access to shared memory |
| must be synchronized. The <code><a href="http://golang.org/pkg/sync/" |
| target="_blank">sync</a></code> package provides useful primitives, |
| although you won't need them much in Go as there are other primitives. |
| (See the next slide.) |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "<span class="appengineMode">runtime</span><span class="localMode">time</span>" |
| ) |
| |
| func say(s string) { |
| for i := 0; i < 5; i++ { |
| <span class="appengineMode">runtime.Gosched()</span><span class="localMode">time.Sleep(100 * time.Millisecond)</span> |
| fmt.Println(s) |
| } |
| } |
| |
| func main() { |
| go say("world") |
| say("hello") |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Channels</h2> |
| |
| <p> |
| Channels are a typed conduit through which you can send and receive values with the channel operator, <code><-</code>. |
| <pre>ch <- v // Send v to channel ch. |
| v := <-ch // Receive from ch, and |
| // assign value to v.</pre> |
| <p> |
| (The data flows in the direction of the arrow.) |
| |
| <p> |
| Like maps and slices, channels must be created before use: |
| <pre>ch := make(chan int)</pre> |
| |
| <p> |
| By default, sends and receives block until the other side is ready. |
| This allows goroutines to synchronize without explicit locks or |
| condition variables. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func sum(a []int, c chan int) { |
| sum := 0 |
| for _, v := range a { |
| sum += v |
| } |
| c <- sum // send sum to c |
| } |
| |
| func main() { |
| a := []int{7, 2, 8, -9, 4, 0} |
| |
| c := make(chan int) |
| go sum(a[:len(a)/2], c) |
| go sum(a[len(a)/2:], c) |
| x, y := <-c, <-c // receive from c |
| |
| fmt.Println(x, y, x + y) |
| }</pre> |
| </div> |
| |
| |
| <div class="slide"> |
| <h2>Buffered Channels</h2> |
| |
| <p> |
| Channels can be <i>buffered</i>. Provide the buffer length as the |
| second argument to <code>make</code> to initialize a buffered channel: |
| <pre>ch := make(chan int, 100)</pre> |
| |
| <p> |
| Sends to a buffered channel block only when the buffer is full. |
| Receives block when the buffer is empty. |
| |
| <p> |
| Modify the example to overfill the buffer and see what happens. |
| |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func main() { |
| c := make(chan int, 2) |
| c <- 1 |
| c <- 2 |
| fmt.Println(<-c) |
| fmt.Println(<-c) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Range and Close</h2> |
| <p> |
| A sender can <code>close</code> a channel to indicate that no more |
| values will be sent. Receivers can test whether a channel has been |
| closed by assigning a second parameter to the receive expression: after |
| <pre>v, ok := <-ch</pre> |
| <p> |
| <code>ok</code> is <code>false</code> if there are no more values to |
| receive and the channel is closed. |
| <p> |
| The loop <code>for i := range c</code> receives values from the |
| channel repeatedly until it is closed. |
| <p> |
| <b>Note:</b> Only the sender should close a channel, never the |
| receiver. Sending on a closed channel will cause a panic. |
| <p> |
| <b>Another note</b>: Channels aren't like files; you don't usually |
| need to close them. Closing is only necessary when the receiver must be |
| told there are no more values coming, such as to terminate a <code>range</code> |
| loop. |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| ) |
| |
| func fibonacci(n int, c chan int) { |
| x, y := 0, 1 |
| for i := 0; i < n; i++ { |
| c <- x |
| x, y = y, x + y |
| } |
| close(c) |
| } |
| |
| func main() { |
| c := make(chan int, 10) |
| go fibonacci(cap(c), c) |
| for i := range c { |
| fmt.Println(i) |
| } |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Select</h2> |
| <p> |
| The <code>select</code> statement lets a goroutine wait on multiple |
| communication operations. |
| <p> |
| A <code>select</code> blocks until one of its cases can run, then it |
| executes that case. It chooses one at random if multiple are ready. |
| <pre class="source">package main |
| |
| import "fmt" |
| |
| func fibonacci(c, quit chan int) { |
| x, y := 0, 1 |
| for { |
| select { |
| case c <- x: |
| x, y = y, x + y |
| case <-quit: |
| fmt.Println("quit") |
| return |
| } |
| } |
| } |
| |
| func main() { |
| c := make(chan int) |
| quit := make(chan int) |
| go func() { |
| for i := 0; i < 10; i++ { |
| fmt.Println(<-c) |
| } |
| quit <- 0 |
| }() |
| fibonacci(c, quit) |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Default Selection</h2> |
| <p> |
| The <code>default</code> case in a <code>select</code> is run if no |
| other case is ready. |
| <p> |
| Use a <code>default</code> case to try a send or receive without |
| blocking: |
| <pre>select { |
| case i := <-c: |
| // use i |
| default: |
| // receiving from c would block |
| }</pre> |
| <p> |
| <span class="appengineMode"> |
| <b>Note:</b> This example won't run through the web-based tour user |
| interface because the sandbox environment has no concept of time. You may want to |
| <a target="_blank" href="http://golang.org/doc/install/">install Go</a> |
| to see this example in action. |
| </span> |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| "time" |
| ) |
| |
| func main() { |
| tick := time.Tick(1e8) |
| boom := time.After(5e8) |
| for { |
| select { |
| case <-tick: |
| fmt.Println("tick.") |
| case <-boom: |
| fmt.Println("BOOM!") |
| return |
| default: |
| fmt.Println(" .") |
| time.Sleep(5e7) |
| } |
| } |
| }</pre> |
| </div> |
| |
| <div class="slide nocode"> |
| <h2>Exercise: Equivalent Binary Trees</h2> |
| <p> |
| There can be many different binary trees with the same sequence of |
| values stored at the leaves. |
| For example, here are two binary trees storing the sequence |
| 1, 1, 2, 3, 5, 8, 13. |
| <img src="static/fig4.png" alt="binary trees"> |
| <p> |
| A function to check whether two binary trees store the same sequence is |
| quite complex in most languages. We'll use Go's concurrency and |
| channels to write a simple solution. |
| <p> |
| This example uses the <code>tree</code> package, which defines the type: |
| <pre>type Tree struct { |
| Left *Tree |
| Value int |
| Right *Tree |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Exercise: Equivalent Binary Trees</h2> |
| <p> |
| <b>1.</b> Implement the <code>Walk</code> function. |
| <p> |
| <b>2.</b> Test the <code>Walk</code> function. |
| <p> |
| The function <code>tree.New(k)</code> constructs a randomly-structured |
| binary tree holding the values <code>k</code>, <code>2k</code>, <code>3k</code>, ..., |
| <code>10k</code>. |
| <p> |
| Create a new channel <code>ch</code> and kick off the walker: |
| <pre>go Walk(tree.New(1), ch)</pre> |
| <p> |
| Then read and print 10 values from the channel. |
| It should be the numbers 1, 2, 3, ..., 10. |
| <p> |
| <b>3.</b> Implement the <code>Same</code> function using <code>Walk</code> |
| to determine whether <code>t1</code> and <code>t2</code> store the same values. |
| <p> |
| <b>4.</b> Test the <code>Same</code> function. |
| <p> |
| <code>Same(tree.New(1), tree.New(1))</code> should return true, and |
| <code>Same(tree.New(1), tree.New(2))</code> should return false. |
| |
| <pre class="source">package main |
| |
| import "<span class="appengineMode">tour</span><span class="localMode">code.google.com/p/go-tour</span>/tree" |
| |
| // Walk walks the tree t sending all values |
| // from the tree to the channel ch. |
| func Walk(t *tree.Tree, ch chan int) |
| |
| // Same determines whether the trees |
| // t1 and t2 contain the same values. |
| func Same(t1, t2 *tree.Tree) bool |
| |
| func main() { |
| }</pre> |
| </div> |
| |
| <div class="slide"> |
| <h2>Exercise: Web Crawler</h2> |
| <p> |
| In this exercise you'll use Go's concurrency features to |
| parallelize a web crawler. |
| <p> |
| Modify the <code>Crawl</code> function to fetch URLs in parallel |
| without fetching the same URL twice. |
| <pre class="source">package main |
| |
| import ( |
| "fmt" |
| ) |
| |
| type Fetcher interface { |
| // Fetch returns the body of URL and |
| // a slice of URLs found on that page. |
| Fetch(url string) (body string, urls []string, err error) |
| } |
| |
| // Crawl uses fetcher to recursively crawl |
| // pages starting with url, to a maximum of depth. |
| func Crawl(url string, depth int, fetcher Fetcher) { |
| // TODO: Fetch URLs in parallel. |
| // TODO: Don't fetch the same URL twice. |
| // This implementation doesn't do either: |
| if depth <= 0 { |
| return |
| } |
| body, urls, err := fetcher.Fetch(url) |
| if err != nil { |
| fmt.Println(err) |
| return |
| } |
| fmt.Printf("found: %s %q\n", url, body) |
| for _, u := range urls { |
| Crawl(u, depth-1, fetcher) |
| } |
| return |
| } |
| |
| func main() { |
| Crawl("http://golang.org/", 4, fetcher) |
| } |
| |
| |
| // fakeFetcher is Fetcher that returns canned results. |
| type fakeFetcher map[string]*fakeResult |
| |
| type fakeResult struct { |
| body string |
| urls []string |
| } |
| |
| func (f *fakeFetcher) Fetch(url string) (string, []string, error) { |
| if res, ok := (*f)[url]; ok { |
| return res.body, res.urls, nil |
| } |
| return "", nil, fmt.Errorf("not found: %s", url) |
| } |
| |
| // fetcher is a populated fakeFetcher. |
| var fetcher = &fakeFetcher{ |
| "http://golang.org/": &fakeResult{ |
| "The Go Programming Language", |
| []string{ |
| "http://golang.org/pkg/", |
| "http://golang.org/cmd/", |
| }, |
| }, |
| "http://golang.org/pkg/": &fakeResult{ |
| "Packages", |
| []string{ |
| "http://golang.org/", |
| "http://golang.org/cmd/", |
| "http://golang.org/pkg/fmt/", |
| "http://golang.org/pkg/os/", |
| }, |
| }, |
| "http://golang.org/pkg/fmt/": &fakeResult{ |
| "Package fmt", |
| []string{ |
| "http://golang.org/", |
| "http://golang.org/pkg/", |
| }, |
| }, |
| "http://golang.org/pkg/os/": &fakeResult{ |
| "Package os", |
| []string{ |
| "http://golang.org/", |
| "http://golang.org/pkg/", |
| }, |
| }, |
| }</pre> |
| </div> |
| |
| <div class="slide nocode"> |
| <h2>Where to Go from here...</h2> |
| <p class="appengineMode"> |
| You can get started by |
| <a href="http://golang.org/doc/install/">installing Go</a> or downloading the |
| <a href="http://code.google.com/appengine/downloads.html#Google_App_Engine_SDK_for_Go">Go App Engine SDK</a>. |
| </p> |
| <p> |
| <span class="appengineMode">Once you have Go on your machine, the</span> |
| <span class="localMode">The</span> |
| <a target="_blank" href="http://golang.org/doc/">Go Documentation</a> is a great place to |
| <span class="appengineMode">continue</span> |
| <span class="localMode">start</span>. |
| It contains references, tutorials, videos, and more. |
| <p> |
| If you need help with the standard library, |
| see the <a target="_blank" href="http://golang.org/pkg/">package reference</a>. |
| For help with the language itself, you might be surprised to find the |
| <a target="_blank" href="http://golang.org/ref/spec">Language Spec</a> is quite readable. |
| <p> |
| To further explore Go's concurrency model, see the |
| <a target="_blank" href="http://golang.org/doc/codewalk/sharemem/">Share Memory by Communicating</a> |
| codewalk. |
| <p> |
| The <a target="_blank" href="http://golang.org/doc/codewalk/functions/">First Class Functions in Go</a> |
| codewalk gives an interesting perspective on Go's function types. |
| <p> |
| The <a target="_blank" href="http://blog.golang.org/">Go Blog</a> has a |
| large archive of informative Go articles. |
| <p> |
| Visit <a target="_blank" href="http://golang.org">golang.org</a> for more. |
| </div> |
| |
| </div><!-- end slides --> |
| |
| <div id="workspace"> |
| <div class="controls"> |
| <div><a id="run" href="#run" title="Compile and Run">Run</a><a href="#more" id="more" title="Options">▼</a></div> |
| <ul class="more"> |
| <li><a href="#" id="reset">Reset Slide</a></li> |
| <li><a href="#" id="format">Format Source Code</a></li> |
| <li><a href="#" id="kill" class="localMode">Kill Program</a></li> |
| <li><hr></li> |
| <li><a href="#" id="togglesyntax">Syntax-Highlighting: off</a></li> |
| <li><a href="#" id="togglelineno">Line-Numbers: on</a></li> |
| </ul> |
| </div> |
| |
| <div id="workspace-top"> |
| <div id="workspace-editor"> |
| <textarea id="editor" spellcheck="false"></textarea> |
| </div> |
| </div> |
| |
| <div id="workspace-bottom"> |
| <div id="output"></div> |
| </div> |
| </div> |
| </div> |
| |
| </body> |
| </html> |