A Tour of Go Exerciseの解答まとめ
A Tour of Go Exerciseの解答まとめ
A Tour of Goを終えたのでExerciseの解答を残しておきます。
すべて自力で解答しています。
答え合わせはこちらを参考にさせていただきました。
Exercise: Loops and Functions
package main import ( "fmt" "math" ) func Sqrt(x float64) float64 { z := 1.0 for dz := z; math.Abs(dz) > 1e-12; z -= dz { dz = (z*z - x) / (2 * z) fmt.Println(dz, z) } return z } func main() { fmt.Println(Sqrt(10)) fmt.Println(math.Sqrt(10)) }
Exercise: Slices
package main import "golang.org/x/tour/pic" func Pic(dx, dy int) [][]uint8 { pic := make([][]uint8, dy) for y := range pic { pic[y] = make([]uint8, dx) for x := range pic[y] { //pic[y][x] = uint8((x + y) / 2) pic[y][x] = uint8(x * x) } } return pic } func main() { pic.Show(Pic) }
Exercise: Maps
package main import ( "strings" "golang.org/x/tour/wc" ) func WordCount(s string) map[string]int { words := strings.Fields(s) result := make(map[string]int) for _, word := range words { result[word]++ } return result } func main() { wc.Test(WordCount) }
Exercise: Fibonacci closure
package main import "fmt" // fibonacci is a function that returns // a function that returns an int. func fibonacci() func() int { num1, num2 := 0, 1 return func() int { num := num1 num1, num2 = num2, num1+num2 return num } } func main() { f := fibonacci() for i := 0; i < 10; i++ { fmt.Println(f()) } }
Exercise: Stringers
package main import "fmt" type IPAddr [4]byte 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}, "googleNDS": {8, 8, 8, 8}, } for name, ip := range hosts { fmt.Printf("%v: %v\n", name, ip) } }
Exercise: Errors
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.0 { return x, ErrNegativeSqrt(x) } z := 1.0 for dz := z; math.Abs(dz) > 1e-12; z -= dz { dz = (z*z - x) / (2 * z) } return z, nil } func main() { fmt.Println(Sqrt(2)) fmt.Println(Sqrt(-2)) }
Exercise: Readers
package main import "golang.org/x/tour/reader" type MyReader struct{} func (r MyReader) Read(b []byte) (int, error) { for i := range b { b[i] = 'A' } return len(b), nil } func main() { reader.Validate(MyReader{}) }
Exercise: rot13Reader
package main import ( "io" "os" "strings" ) type rot13Reader struct { r io.Reader } func (rot rot13Reader) Read(b []byte) (int, error) { n, err := rot.r.Read(b) for i, value := range b { diff := value - 'A' if (diff >= 0 && diff < 13) || (diff >= 32 && diff < 45) { b[i] += 13 } else { b[i] -= 13 } } return n, err } func main() { s := strings.NewReader("Lbh penpxrq gur pbqr!") r := rot13Reader{s} io.Copy(os.Stdout, &r) }
Exercise: Images
package main import ( "golang.org/x/tour/pic" "math/rand" "time" "image" "image/color" ) type Image struct{} func (img Image) Bounds() image.Rectangle { return image.Rect(0, 0, 160, 120) } func (img Image) ColorModel() color.Model { return color.RGBAModel } func (img Image) At(x, y int) color.Color { return color.RGBA{uint8(rand.Intn(255)), uint8(rand.Intn(255)), 255, 255} } func main() { rand.Seed(time.Now().UnixNano()) m := Image{} pic.ShowImage(m) }
Exercise: Equivalent Binary Trees
package main import ( "fmt" "golang.org/x/tour/tree" ) 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) } } 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++ { if <-ch1 != <-ch2 { return false } } return true } func main() { ch := make(chan int) go Walk(tree.New(1), ch) for i := 0; i < 10; i++ { fmt.Println(<-ch) } fmt.Println(Same(tree.New(1), tree.New(1))) fmt.Println(Same(tree.New(1), tree.New(2))) }
Exercise: Web Crawler
package main import ( "fmt" "sync" ) type Fetcher interface { Fetch(url string) (body string, urls []string, err error) } func (fetched *FetchedURLs) Crawl(url string, depth int, fetcher Fetcher) { if depth <= 0 { fetched.wg.Done() return } fetched.mux.Lock() if fetched.urls[url] { defer fetched.mux.Unlock() fetched.wg.Done() return } body, urls, err := fetcher.Fetch(url) if err != nil { fmt.Println(err) fetched.urls[url] = true defer fetched.mux.Unlock() fetched.wg.Done() return } fetched.urls[url] = true defer fetched.mux.Unlock() fmt.Printf("found: %s %q\n", url, body) for _, u := range urls { fetched.wg.Add(1) go fetched.Crawl(u, depth-1, fetcher) } fetched.wg.Done() return } func main() { fetched := FetchedURLs{urls: make(map[string]bool)} fetched.wg.Add(1) go fetched.Crawl("https://golang.org/", 4, fetcher) fetched.wg.Wait() } type fakeFetcher map[string]*fakeResult type FetchedURLs struct { urls map[string]bool mux sync.Mutex wg sync.WaitGroup } 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) } 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/", }, }, }