# A Tour of Go练习题汇总

## 1. fibonacci的三种写法

func fibonacci() func() int {
x, y := 1, 0
return func() int {
x, y = y, x+y
return x
}
}

func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}

func fibonacci2(n int, c chan int) {
x, y := 1, 0
for i := 0; i < n; i++ {
x, y = y, x+y
c <- x
}
close(c)
}

func main() {
c := make(chan int, 10)
go fibonacci2(cap(c), c)
for v := range c {
fmt.Println(v)
}
}

func fibonacci3(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
}()

fibonacci3(c, quit)
}

rot13是一种简单的字符加密算法，也就是把每个字符向后移动13位，具体参见下图：

package main

import (
"io"
"os"
"strings"
)

}

if err == io.EOF {
return 0, io.EOF
}

for i, c := range b {
switch {
case c < 'N':
b[i] = c + 13
case c <= 'Z':
b[i] = c - 13
case c < 'n':
b[i] = c + 13
case c <= 'z':
b[i] = c - 13
default:
b[i] = c
}
}

return n, nil
}

func main() {
s := strings.NewReader("Lbh penpxrq gur pbqr!")
io.Copy(os.Stdout, &r)
}

## 3. 比较二叉平衡树内容是否相同

package main

import "fmt"
import "golang.org/x/tour/tree"

// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int) {
WalkInternal(t, ch)
close(ch)
}

func WalkInternal(t *tree.Tree, ch chan int) {
if t != nil {
WalkInternal(t.Left, ch)
ch <- t.Value
WalkInternal(t.Right, ch)
}
}

// Same determines whether the trees
// t1 and t2 contain the same values.
func Same(t1, t2 *tree.Tree) bool {
c1, c2 := make(chan int), make(chan int)

go Walk(t1, c1)
go Walk(t2, c2)

for {
v1, ok1 := <-c1
v2, ok2 := <-c2

if ok1 != ok2 || v1 != v2 {
return false
}

if ok1 == false {
break
}
}

return true
}

func main() {
ch := make(chan int)
go Walk(tree.New(1), ch)
for i := range ch {
fmt.Println(i)
}

fmt.Println(Same(tree.New(1), tree.New(1)))
fmt.Println(Same(tree.New(1), tree.New(2)))
}

## 4. 网络爬虫性能优化

a) 每个URL只需要被爬取一次

b) 并行爬取多个URL

package main

import (
"fmt"
"sync"
"time"
)

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
}

if cache.has(url) {
fmt.Println("Hit cache")
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 {
go Crawl(u, depth-1, fetcher)
}
return
}

type Cache struct {
cache map[string]bool
mutex sync.Mutex
}

func (cache *Cache) add(url string) {
cache.mutex.Lock()
cache.cache[url] = true
cache.mutex.Unlock()
}

func (cache *Cache) has(url string) bool {
cache.mutex.Lock()
defer cache.mutex.Unlock()
_, ok := cache.cache[url]
if !ok {
cache.cache[url] = true
}
return ok
}

var cache Cache = Cache{
cache: make(map[string]bool),
}

func main() {
Crawl("https://golang.org/", 4, fetcher)
time.Sleep(2000 * time.Millisecond)
}

// 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
}
}

// fetcher is a populated fakeFetcher.
var fetcher = fakeFetcher{
"https://golang.org/": &fakeResult{
"The Go Programming Language",
[]string{
"https://golang.org/pkg/",
"https://golang.org/cmd/",
},
},
"https://golang.org/pkg/": &fakeResult{
"Packages",
[]string{
"https://golang.org/",
"https://golang.org/cmd/",
"https://golang.org/pkg/fmt/",
"https://golang.org/pkg/os/",
},
},
"https://golang.org/pkg/fmt/": &fakeResult{
"Package fmt",
[]string{
"https://golang.org/",
"https://golang.org/pkg/",
},
},
"https://golang.org/pkg/os/": &fakeResult{
"Package os",
[]string{
"https://golang.org/",
"https://golang.org/pkg/",
},
},
}

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120