我试着玩了一下《A Tour of Go》

个人的想法

这次训练的主题很好。

我写的代码

循环和函数。

package main

import (
    "fmt"
    "math"
)

func Sqrt(x float64) float64 {
  z := 1.0
  for math.Abs(z*z - x) > 1e-10 {
    z -= (z*z - x) / (2*z)
    fmt.Println(z)
  }
  return z
}

func main() {
    fmt.Println(Sqrt(2))
}

切片

package main

import "golang.org/x/tour/pic"

func Pic(dx, dy int) [][]uint8 {
    rows := make([][]uint8, dy)
    for y:=0; y<dy; y++ {
        cols := make([]uint8, dx)
        for x:=0; x<dx; x++ {
            cols[x] = uint8(x^y)
        }
        rows[y] = cols
    }
    return rows
}

func main() {
    pic.Show(Pic)
}k

地图 (dì tú)

package main

import (
    "golang.org/x/tour/wc"
    "strings"
)

func WordCount(s string) map[string]int {
    m := make(map[string]int)
    for _, x := range strings.Fields(s) {
        m[x]++
    }
    return m
}

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 {
    x0, x1 := 0, 1
    return func() int {
        v := x0
        x0, x1 = x1, x0+x1
        return v
    }
}

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

線索者

package main

import "fmt"

type IPAddr [4]byte

// TODO: Add a "String() string" method to IPAddr.
func (x IPAddr) String() string {
    return fmt.Sprintf("%d.%d.%d.%d", x[0], x[1], x[2], x[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\n", name, ip)
    }
}

错误

package main

import (
    "fmt"
    "math"
)

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 x, ErrNegativeSqrt(x)
  }
  z := 1.0
  for math.Abs(z*z - x) > 1e-10 {
    z -= (z*z - x) / (2*z)
  }
  return z, nil
}

func main() {
    fmt.Println(Sqrt(2))
    fmt.Println(Sqrt(-2))
}

读者 (dú zhě)

package main

import "golang.org/x/tour/reader"

type MyReader struct{}

// TODO: Add a Read([]byte) (int, error) method to MyReader.
func (r MyReader) Read(bs []byte) (int, error) {
    bs[0] = 'A'
    return 1, nil
}

func main() {
    reader.Validate(MyReader{})
}

旋转3读者

package main

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

type rot13Reader struct {
    r io.Reader
}

func (reader *rot13Reader) Read(bs []byte) (int, error) {
    bs2 := make([]byte, 100)
    n, err := reader.r.Read(bs2)
    if err != nil {
        return 0, err
    }

    decode := func(base byte, c byte) byte {
        c -= base
        c = (c + 13) % 26
        return c + base
    }
    for i := 0; i < n; i++ {
        c := bs2[i]
        if 'a' <= c && c <= 'z' {
            bs[i] = decode('a', c)
        } else if 'A' <= c && c <= 'Z' {
            bs[i] = decode('A', c)
        } else {
            bs[i] = c
        }
    }
    return n, nil
}

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

图像

package main

import (
    "golang.org/x/tour/pic"
    "image"
    "image/color"
)

type Image struct {
    width  int
    height int
    body   [][]uint8
}

func (i Image) ColorModel() color.Model {
    return color.RGBAModel
}

func (i Image) Bounds() image.Rectangle {
    return image.Rect(0, 0, i.width, i.height)
}

func (i Image) At(x, y int) color.Color {
    v := i.body[y][x]
    return color.RGBA{v, v, 255, 255}
}

func genBody(dx, dy int) [][]uint8 {
    rows := make([][]uint8, dy)
    for y := 0; y < dy; y++ {
        cols := make([]uint8, dx)
        for x := 0; x < dx; x++ {
            cols[x] = uint8(x ^ y)
        }
        rows[y] = cols
    }
    return rows
}

func main() {
    body := genBody(100, 100)
    image := Image{100, 100, body}
    pic.ShowImage(image)
}

等值的二进制树

package main

import (
    "fmt"
    "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) {
    if t.Left != nil {
        Walk(t.Left, ch)
    }
    ch <- t.Value
    if t.Right != nil {
        Walk(t.Right, ch)
    }
}

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

    for i := 0; i < 10; i++ {
        if <-c1 != <-c2 {
            return false
        }
    }
    return true
}

func main() {
    t1 := tree.New(1)
    t2 := tree.New(2)
    fmt.Println(Same(t1, t2))
}

网络爬虫

package main

import (
    "fmt"
    "sync"
)

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

type Cache struct {
    mu   sync.Mutex
    urls map[string]struct{}
}

func (c *Cache) Has(url string) bool {
    c.mu.Lock()
    defer c.mu.Unlock()
    _, ok := c.urls[url]
    return ok
}

func (c *Cache) Add(url string) {
    c.mu.Lock()
    c.urls[url] = struct{}{}
    c.mu.Unlock()
}

// Crawl uses fetcher to recursively crawl
// pages starting with url, to a maximum of depth.
func Crawl(url string, depth int, fetcher Fetcher, cache *Cache, wg *sync.WaitGroup) {
    defer wg.Done()

    if depth <= 0 || cache.Has(url) {
        return
    }
    cache.Add(url)

    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 {
        wg.Add(1)
        go Crawl(u, depth-1, fetcher, cache, wg)
    }
}

func main() {
    wg := sync.WaitGroup{}
    cache := Cache{urls: make(map[string]struct{})}
    wg.Add(1)
    go Crawl("https://golang.org/", 4, fetcher, &cache, &wg)
    wg.Wait()
}

// 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{
    "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/",
        },
    },
}
bannerAds