golang官方指导练习(go tour exercise)

2019-04-15 13:05发布

本文是golang官方练习的pass代码,使用了中文版的tour

循环与函数

package main import ( "fmt" ) func Sqrt(x float64) float64 { res := 1.0 for i := 0; i < 10; i++ { res = res - (res * res - x) / 2 / res } return res } func main() { fmt.Println(Sqrt(2)) }

slice

package main import "golang.org/x/tour/pic" func Pic(dx, dy int) [][]uint8 { var pic [][]uint8; for i := 0; i < dy; i++ { var one_line []uint8 for j := 0; j < dx; j++ { one_line = append(one_line, (uint8)(i & j)) } pic = append(pic, one_line) } return pic } func main() { pic.Show(Pic) }

map

package main import ( "golang.org/x/tour/wc" "strings" ) func WordCount(s string) map[string]int { count := make(map[string]int) for _, v := range strings.Fields(s) { count[v] = count[v] + 1 } return count } func main() { wc.Test(WordCount) }

斐波纳契闭包

package main import "fmt" // fibonacci is a function that returns // a function that returns an int. func fibonacci() func() int { one := 0 two := 1 return func() int { result := one one = two two = result + two return result } } func main() { f := fibonacci() for i := 0; i < 10; i++ { fmt.Println(f()) } }

stringer

package main import "fmt" type IPAddr [4]byte // TODO: Add a "String() string" method to IPAddr. func (IP IPAddr) String() string { return fmt.Sprintf("%v.%v.%v.%v", IP[0], IP[1], IP[2], IP[3]) } func main() { hosts := map[string]IPAddr{ "loopback": {127, 0, 0, 1}, "googleDNS": {8, 8, 8, 8}, } for name, ip := range hosts { fmt.Printf("%v: %v ", name, ip) } }

error

package main import ( "fmt" ) type ErrNegativeSqrt float64 func (e ErrNegativeSqrt) Error() string { return fmt.Sprintf("cannot Sqrt negative number: %v", float64(e)) } func Sqrt(x float64) (float64, error) { if x < 0 { return 0, ErrNegativeSqrt(x) } res := 1.0 for i := 0; i < 10; i++ { res = res - (res * res - x) / 2 / res } return res, nil } func main() { fmt.Println(Sqrt(2)) fmt.Println(Sqrt(-2)) }

Reader

package main import "github.com/Go-zh/tour/reader" type MyReader struct{} // TODO: Add a Read([]byte) (int, error) method to MyReader. func (r MyReader) Read(p []byte) (int, error) { for i := 0; i < len(p); i++ { p[i] = 'A' } return len(p), nil } func main() { reader.Validate(MyReader{}) }

rot13Reader

package main import ( "io" "os" "strings" ) type rot13Reader struct { r io.Reader } func (self rot13Reader) Read(buf []byte) (int, error) { length, err := self.r.Read(buf) if err != nil { return length, err } for i := 0; i < length; i++ { v := buf[i] switch { case 'a' <= v && v <= 'm': fallthrough case 'A' <= v && v <= 'M': buf[i] = v + 13 case 'n' <= v && v <= 'z': fallthrough case 'N' <= v && v <= 'Z': buf[i] = v - 13 } } return length, nil } func main() { s := strings.NewReader("Lbh penpxrq gur pbqr!") r := rot13Reader{s} io.Copy(os.Stdout, &r) }

image

package main import ( "golang.org/x/tour/pic" "image" "image/color" ) type Image struct{ w int h int } func (self Image) ColorModel() color.Model { return color.RGBAModel } func (self Image) Bounds() image.Rectangle { return image.Rect(0, 0, self.w, self.h) } func (self Image) At(x, y int) color.Color { r := (uint8)((float64)(x) / (float64)(self.w) * 255.0) g := (uint8)((float64)(y) / (float64)(self.h) * 255.0) b := (uint8)((float64)(x * y) / (float64)(self.w * self.h) * 255.0) return color.RGBA{r, g, b, 255} } func main() { m := Image{255, 255} pic.ShowImage(m) }

等价二叉树

package main import ( "fmt" "golang.org/x/tour/tree" ) // Walk 步进 tree t 将所有的值从 tree 发送到 channel ch。 func Walk(t *tree.Tree, ch chan int) { if t == nil { return } Walk(t.Left, ch) ch <- t.Value Walk(t.Right, ch) } // Same 检测树 t1 和 t2 是否含有相同的值。 func Same(t1, t2 *tree.Tree) bool { ch1 := make(chan int) ch2 := make(chan int) go Walk(t1, ch1) go Walk(t2, ch2) for i := 0; i < 10; i++ { x, y := <-ch1, <-ch2 fmt.Println(x, y) if x != y { return false } } return true } func main() { fmt.Println(Same(tree.New(1), tree.New(1))) }

Web 爬虫

package main import ( "fmt" "sync" ) type Fetcher interface { // Fetch 返回 URL 的 body 内容,并且将在这个页面上找到的 URL 放到一个 slice 中。 Fetch(url string) (body string, urls []string, err error) } // Crawl 使用 fetcher 从某个 URL 开始递归的爬取页面,直到达到最大深度。 func Crawl(url string, depth int, fetcher Fetcher, crawled Crawled, out chan string, end chan bool) { // TODO: 并行的抓取 URL。 // TODO: 不重复抓取页面。 // 下面并没有实现上面两种情况: if depth <= 0 { end <- true return } crawled.mux.Lock() if _, ok := crawled.crawled[url]; ok { crawled.mux.Unlock() end <- true return } crawled.crawled[url] = 1 crawled.mux.Unlock() _, urls, err := fetcher.Fetch(url) if err != nil { fmt.Println(err) end <- true return } out <- url //fmt.Println("found: ", url, body) for _, u := range urls { go Crawl(u, depth-1, fetcher, crawled, out, end) } for i := 0; i < len(urls); i++ { <-end } end <- true return } type Crawled struct { crawled map[string]int mux sync.Mutex } func main() { crawled := Crawled{make(map[string]int), sync.Mutex{}} out := make(chan string) end := make(chan bool) go Crawl("http://golang.org/", 4, fetcher, crawled, out, end) for { select { case url := <-out: fmt.Println("found: ", url) case <-end: return } } } // fakeFetcher 是返回若干结果的 Fetcher。 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 是填充后的 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/", }, }, }