A Tour of Go 的练习题目

练习:循环和函数

package main

import (
    "fmt"
    "math"
)

const eps = 1e-9

func Sqrt(x float64) float64 {
    z := 1.0
    p := z

    for {
        z = z - (z * z - x) / (2 * z)
        if math.Abs(z - p) < eps {
            break
        }
        p = z
    }

    return z
}

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

运动:薄片

package main

import "code.google.com/p/go-tour/pic"

func Pic(dx, dy int) [][]uint8 {
    image := make([][]uint8, dy)
    for y := range image {
        image[y] = make([]uint8, dx)
    }

    for y := 0; y < dy; y++ {
        for x :=0; x < dx; x++ {
            image[y][x] = uint8((x + y) / 2)
        }
    }

    return image

}

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

锻炼:地图

package main

import (
    "code.google.com/p/go-tour/wc"
    "strings"
)

func WordCount(s string) map[string]int {
    countMap := map[string]int{}

    for _, word := range strings.Fields(s) {
        countMap[word]++
    }

    return countMap
}

func main() {
    wc.Test(WordCount)
}

练习:斐波那契闭包

package main

import "fmt"

func fibonacci() func() int {
    a, b := 0, 1

    return func() int {
        a, b = b, a + b
        return a
    }
}

func main() {
    f := fibonacci()

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

高级练习:复杂立方根

package main

import (
    "fmt"
    "math/cmplx"
)

const eps = 1e-9

func Cbrt(x complex128) complex128 {
    z := 1 + 0i
    p := z

    for {
        z = z - (z * z * z - x) / (3 * z * z)
        if cmplx.Abs(z - p) < eps {
            break
        }
        p = z
    }

    return z
}

func main() {
    fmt.Println(cmplx.Pow(2 + 5i, 1.0/3))
    fmt.Println(Cbrt(2 + 5i))
}

练习:错误

package main

import (
    "fmt"
    "math"
)

type ErrNegativeSqrt float64

func (e ErrNegativeSqrt) Error() string {
    return fmt.Sprintf("cannot Sqrt negative number: %f", e)
}


const eps = 1e-9

func Sqrt(x float64) (float64, error) {
    if x < 0 {
        return 0, ErrNegativeSqrt(x)
    }
    z := 1.0
    p := z

    for {
        z = z - (z * z - x) / (2 * z)
        if math.Abs(z - p) < eps {
            break
        }
        p = z
    }

    return z, nil
}

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

练习:HTTP 处理程序

package main

import (
    "fmt"
    "net/http"
)

type String string

func (s String) ServeHTTP(w http.ResponseWriter, r *http.Request){
    fmt.Fprintf(w, "%s", s)
}

type Struct struct {
    Greeting string
    Punct    string
    Who      string
}

func (s *Struct) ServeHTTP(w http.ResponseWriter, r *http.Request){
    fmt.Fprintf(w, "%s", s.Who + s.Punct + s.Greeting)
}

func main() {
    http.Handle("/string", String("I like takoyaki"))
    http.Handle("/struct", &Struct{"Hello", ":", "Sam"})
    http.ListenAndServe(":4000", nil)
}

锻炼:图片

package main

import (
    "code.google.com/p/go-tour/pic"
    "image"
    "image/color"
)

type Image struct{}

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

func (im *Image) Bounds() image.Rectangle {
    return image.Rectangle{
        image.Point{0, 0},
        image.Point{200, 200},
    }
}

func (im *Image) At(x, y int) color.Color {
    return color.RGBA{uint8(x % 256), uint8(y %  256), uint8((x * y) % 256 ), 255}
}

func main() {
    m := Image{}
    pic.ShowImage(&m)
}

练习:Rot13阅读器

package main

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

type rot13Reader struct {
    r io.Reader
}

func rot13(b byte) byte {
    if 'A' <= b && b <= 'Z' {
        k := b - 'A'
        return 'A' + (k - 13 + 26) % 26
    }
    if 'a' <= b && b <= 'z' {
        k := b - 'a'
        return 'a' + (k - 13 + 26) % 26
    }
    return b
}

func (rot *rot13Reader) Read(p []byte) (int, error){
    nr, ne := rot.r.Read(p)
    if ne != nil {
        return nr, ne
    }

    for i:=0; i<nr; i++ {
        p[i] = rot13(p[i])
    }

    return nr, nil
}

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

练习:等价的二进制树

http://go-tour-jp.appspot.com/#70
在这个网址上,你可以参观一个Go语言的教学网站,它教你如何创建等价的二叉树。

http://stackoverflow.com/questions/12224042/go-tour-exercise-equivalent-binary-trees
这个问题在Stack Overflow上问到了如何使用Go语言来练习创建等价的二叉树。

package main

import "code.google.com/p/go-tour/tree"
import "fmt"

// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int){
    var walker func(*tree.Tree)
    walker = func(t *tree.Tree) {
        if t.Left != nil {
            walker(t.Left)
        }

        ch <- t.Value

        if t.Right != nil {
            walker(t.Right)
        }
    }

    walker(t)
    close(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 {
        n1, ok1 := <-c1
        n2, ok2 := <-c2

        if n1 != n2 || ok1 != ok2 {
            return false
        }

        if !ok1 {
            break
        }
    }

    return true
}

func main() {
    fmt.Println(Same(tree.New(1), tree.New(1)))
    fmt.Println(Same(tree.New(5), tree.New(5)))
    fmt.Println(Same(tree.New(3), tree.New(2)))
}

练习:网络爬虫

http://go-tour-jp.appspot.com/#71 可以让您在浏览器中学习Go编程语言的互动教程。该教程涵盖了Go语言的语法、数据类型、函数等内容,并提供了许多实践性的例子和练习。

http://c4se.hatenablog.com/entry/2013/01/24/175114 是一篇关于Go编程语言的博文。在这篇博文中,作者介绍了Go的一些特性和优势,并分享了自己的学习心得和体会。如果您对Go编程感兴趣,这篇博文可以作为您的参考资料。

在另一个版本中,修正了当深度小于等于0时的处理方式。

package main

import (
    "fmt"
    "time"
)

type Fetcher interface {
    Fetch(url string) (body string, urls []string, err error)
}

func Crawl(url string, depth int, fetcher Fetcher) {
    type URL struct {
        url   string
        depth int
    }

    msg  := make(chan string)
    req  := make(chan URL)
    quit := make(chan int)

    crawler := func (url string, depth int) {
        defer func() { quit <- 0 }()

        if depth <= 0 {
            return
        }

        body, urls, err := fetcher.Fetch(url)

        if err != nil {
            msg <- fmt.Sprintf("%s\n", err)
            return
        }

        msg <- fmt.Sprintf("found: %s %q\n", url, body)

        for _, u := range urls {
            req <- URL{ u, depth - 1 }
        }
    }

    works := 1

    memo := make(map[string]bool)
    memo[url] = true

    go crawler(url, depth)

    for works > 0 {
        select {
            case s := <-msg:
                fmt.Print(s)
            case u := <-req:
                if !memo[u.url] {
                    memo[u.url] = true
                    works++

                    go crawler(u.url, u.depth)
                }
            case <- quit:
                works--
        }
    }
}


func main() {
    Crawl("http://golang.org/", 4, fetcher)
}


type fakeFetcher map[string]*fakeResult

type fakeResult struct {
    body string
    urls []string
}

func (f fakeFetcher) Fetch(url string) (string, []string, error) {
    time.Sleep(time.Second * 5)
    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/",
        },
    },
}

练习:网络爬虫 另一个版本

由于上面的版本会被阻止,所以我也写了一个不被阻止的版本。
另外,处理 depth <= 0 的地方有错误,所以我也做出了修正。
感觉这个版本更清爽一些。

package main

import (
    "fmt"
    "time"
)

type Fetcher interface {
    Fetch(url string) (body string, urls []string, err error)
}

func Crawl(url string, depth int, fetcher Fetcher) {
    type Msg struct {
        message string
    }
    type URL struct {
        url   string
        depth int
    }
    type Quit struct{}

    ch := make(chan interface{}, 20)
    crawler := func (url string, depth int) {
        defer func() { ch <- Quit{} }()

        body, urls, err := fetcher.Fetch(url)

        if err != nil {
            ch <- Msg{ fmt.Sprintf("%s\n", err) }
            return
        }

        ch <- Msg{ fmt.Sprintf("found: %s %q\n", url, body) }

        for _, u := range urls {
            ch <- URL{ u, depth - 1 }
        }
    }

    works := 0
    memo  := make(map[string]bool)

    ch <- URL{ url, depth }

    for {
        req := <- ch

        switch req := req.(type) {
            case Msg:
                fmt.Print(req.message)
            case URL:
                if req.depth > 0 && !memo[req.url] {
                    memo[req.url] = true
                    works++

                    go crawler(req.url, req.depth)
                }
            case Quit:
                works--
        }

        if works <= 0 {
            break
        }
    }
}


func main() {
    Crawl("http://golang.org/", 4, fetcher)
}


type fakeFetcher map[string]*fakeResult

type fakeResult struct {
    body string
    urls []string
}

func (f fakeFetcher) Fetch(url string) (string, []string, error) {
    time.Sleep(time.Second * 5)
    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/",
        },
    },
}
广告
将在 10 秒后关闭
bannerAds