X-Tour-Commit: 56b581fc0ce63be689519a69dbc5b4baedd9c9f8
This commit is contained in:
Andrew Gerrand 2011-07-18 17:30:31 +10:00
Родитель c8a64f8188
Коммит 514ccfdd71
1 изменённых файлов: 142 добавлений и 115 удалений

Просмотреть файл

@ -1397,15 +1397,6 @@ func main() {
</div>
</div>
<div class="slide">
<h2>Exercise: Images</h2>
<p>
Let's eliminate some more scaffolding.
<div>
</div>
</div>
<div class="toc">Concurrency</div>
<div class="slide nocode">
@ -1415,14 +1406,18 @@ func main() {
<div class="slide">
<h2>Goroutines</h2>
<p><code>go f(x, y, z)</code> starts a new goroutine running <code>f(x,
y, z)</code>. The evaluation
<p>
<code>go f(x, y, z)</code> starts a new goroutine running <code>f(x,
y, z)</code>.
<p>
The evaluation
of <code>f</code>, <code>x</code>, <code>y</code>, and <code>z</code>
happens in the current goroutine. After they are evaluated, a new goroutine
is created and it calls <code>f</code> with those arguments.
happens in the current goroutine and the execution of <code>f</code>
happens in the new goroutine.
<p>Goroutines share memory, so access to shared memory must be
synchronized. The <code>sync</code> package provides useful primitives.
<p>Goroutines share memory, 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.
<div>
package main
@ -1448,39 +1443,36 @@ func main() {
<div class="slide">
<h2>Channels</h2>
<p>
Channels are typed message buffers with send and receive.
<p>Like maps and slices, channels must be created before use:
<p>
Channels are a typed conduit through which you can send and receive values with the channel operator, <code>&lt;-</code>.
<pre>
ch := make(chan int, 100)
ch <- v // send v to channel ch
v := <-ch // receive from ch, 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>This channel has room for 100 ints in its buffer. Sends block when the
buffer is full. Receives block when there's nothing available. This allows
goroutines to synchronize without explicit locks or condition variables.
<p>If the second arg to <code>make</code> is omitted or zero, the channel is
unbuffered. Sends to an unbuffered channel block until another goroutine
receives from that channel, and receives block until a value is sent.
<p>The built-in function <code>cap(ch)</code> returns the size
of <code>ch</code>'s buffer; <code>len(ch)</code> returns the number of elements
in the buffer ready to be received.
<p>
Sends and receives block until the other side is ready. This allows
goroutines to synchronize without explicit locks or condition
variables.
<div>
package main
import (
"fmt"
)
import "fmt"
func sum(a []int, c chan int) {
res := 0
sum := 0
for _, v := range a {
res += v
sum += v
}
c <- res
c <- sum // send sum to c
}
func main() {
@ -1489,7 +1481,7 @@ func main() {
c := make(chan int)
go sum(a[:len(a)/2], c)
go sum(a[len(a)/2:], c)
x, y := <-c, <-c
x, y := <-c, <-c // receive from c
fmt.Println(x, y, x + y)
}
@ -1497,6 +1489,38 @@ func main() {
</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 only block when the buffer is full.
Receives block when the buffer is empty.
<p>
Modify the example to overfill the buffer and see what happens.
<div>
package main
import "fmt"
func main() {
c := make(chan int, 2)
c <- 1
c <- 2
fmt.Println(<-c)
fmt.Println(<-c)
}
</div>
</div>
<div class="slide">
<h2>Range and Close</h2>
@ -1617,95 +1641,98 @@ func main() {
</div>
<div class="slide">
<h2>Exercise: Web Crawler</h2>
<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="fig4.png">
<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(2))</code> should return true, and
<code>Same(tree.New(1), tree.New(2))</code> should return false.
<p>Change <code>Crawl</code> to run each call to <code>fetcher.Fetch</code> in
its own goroutine and avoid fetching the same URL twice.
<div>
package main
import (
"os"
"fmt"
)
import "go-tour.googlecode.com/hg/tree"
type Fetcher interface {
// Fetch returns the contents of url and a slice
// of URLs on that page that may be crawled.
// It returns an error if url was not found or the fetch failed.
Fetch(url string) (contents string, urls []string, err os.Error)
}
// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int)
// Crawl fetches pages recursively starting from url to depth using fetcher.
func Crawl(url string, depth int, fetcher Fetcher) {
// TODO(you): Run each call to fetcher.Fetch in its own goroutine.
// TODO(you): Don't fetch the same URL twice.
// This implementation doesn't do either:
if depth <= 0 {
return
}
contents, urls, err := fetcher.Fetch(url)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(contents)
for _, u := range urls {
Crawl(u, depth-1, fetcher)
}
return
}
// Fake web of URLs for testing.
type fakeResult struct {
contents string
urls []string
}
type fakeFetcher map[string]*fakeResult
func (f *fakeFetcher) Fetch(url string) (contents string, urls []string, err os.Error) {
if res, ok := (*f)[url]; ok {
return res.contents, res.urls, nil
}
return "", nil, fmt.Errorf("not found: %s", url)
}
// Same determines whether the trees
// t1 and t2 contain the same values.
func Same(t1, t2 *tree.Tree) bool
func main() {
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/pkg/os": &fakeResult{
"Package os",
[]string{},
},
}
Crawl("http://golang.org", 3, fetcher)
}
</div>
</div>
<div class="slide nocode">
<h2>More here...</h2>
<div class="slide">
<h2>Where to Go from here...</h2>
<p>
The <a href="http://golang.org/doc/docs.html">Go Documentation</a> is
a great place to start. It contains references, tutorials, videos, and more.
<p>
If you need help with the standard library,
see the <a href="http://golang.org/pkg/">package reference</a>.
For help with the language itself, you might be surprised to find the
<a href="http://golang.org/doc/go_spec.html">Language Spec</a> is quite readable.
<p>
If you're interested in writing web applications,
see the <a href="http://golang.org/doc/codelab/wiki/">Wiki Codelab</a>.
<p>
If you want to further explore Go's concurrency model, see the
<a href="http://golang.org/doc/codewalk/sharemem/">Share Memory by Communicating</a>
codewalk.
<p>
The <a 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 href="http://blog.golang.org/">Go Blog</a> has a large archive of
informative Go articles.
<p>
Visit <a href="http://golang.org">golang.org</a> for more.
</div>
</div>