Go言語、ウォッチだけしててあまりまじめにやってなかったので昨日からチュートリアルみたいなのやってた。
Go の基本的な文法の軽い解説がありつつ、ブラウザでコード実行しつつ学べるみたいな感じ。 途中でいくつか練習問題みたいなのがあった。 サンドボックスが Google Frontend で動いててちゃんとしてる。
Go のドキュメントとして
とかが参考になった。
感想
- ベター C としてみるといいことしかない
- ところどころ Python っぽい
- range とか 組み込みの len でいろんな型の長さっぽいのが取得できる とか シンタックスシュガーがあまりない とか
- goroutine と channel のおかげでジョブキュー みたいな非同期処理を要求されるミドルウェアが簡単に書けそうだった
- オブジェクト指向をサポートしてる言語からみると、言語機能が少なくて学習コストが小さそう
- おしゃれに抽象化して書けるみたいな要素は少なそう
Rubyのライブラリとか読んでて、綺麗に抽象化されててコード量は少ないけど、その分コードが素直に読めなくなるみたいな世界観はあまり好きではないので、その点 Go は素直なコードに落ち着きそうな感じがしてわりと好き。
以下、練習問題の回答。
#25
package main import ( "fmt" "math" ) func Sqrt(x float64) float64 { z, prev := 2., 0. const threshhold float64 = 1e-10 for i := 0; math.Abs(z - prev) > threshhold; i++ { prev = z z = z - (math.Pow(z, 2) - x) / (2 * z) fmt.Printf("loop %d\n", i + 1) } return z } func main() { fmt.Println(Sqrt(2)) fmt.Println(math.Sqrt(2)) }
#38
package main import "code.google.com/p/go-tour/pic" func Pic(dx, dy int) [][]uint8 { mat := make([][]uint8, dx) for i := range mat { mat[i] = make([]uint8, dy) for j := range mat[i] { mat[i][j] = uint8(i*j) } } return mat } func main() { pic.Show(Pic) }
#43
package main import ( "code.google.com/p/go-tour/wc" "strings" ) func WordCount(s string) map[string]int { countByWord := make(map[string]int) for _, word := range strings.Fields(s) { countByWord[word] += 1 } return countByWord } func main() { wc.Test(WordCount) }
#46
package main import "fmt" // fx+2 = fx + fx+1 func fibonacci() func() int { x, y := 0, 1 return func() int { x, y = y, x + y return x } } func main() { f := fibonacci() for i := 0; i < 10; i++ { fmt.Println(f()) } }
#50
package main import ( "fmt" "math/cmplx" ) func Cbrt(x complex128) complex128 { z, prev := complex128(2), complex128(0) threshhold := 1e-10 for ; cmplx.Abs(z - prev) > threshhold; { prev = z z = z - (cmplx.Pow(z, 3) - x) / (3 * (z*z)) } return z } func main() { fmt.Println(Cbrt(2)) fmt.Println(cmplx.Pow(3, 1.0/3.0)) }
#58
package main import ( "fmt" "math" ) type ErrNegativeSqrt float64 func (e ErrNegativeSqrt) Error() string { return fmt.Sprintf("at %f", e) } func Sqrt(f float64) (float64, error) { if f < 0.0 { return 0., ErrNegativeSqrt(f) } z, prev := 2., 0. const threshhold float64 = 1e-10 for i := 0; math.Abs(z - prev) > threshhold; i++ { prev = z z = z - (math.Pow(z, 2) - f) / (2 * z) fmt.Printf("loop %d\n", i + 1) } return z, nil } func main() { fmt.Println(Sqrt(2)) fmt.Println(Sqrt(-2)) }
#60
package main import ( "fmt" "net/http" ) type String string func (s String) ServeHTTP( w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "%s, %q", s, r.URL.Path) } type Struct struct { Greeting string Punct string Who string } func (s Struct) ServeHTTP( w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "%s, %q", s, r.URL.Path) } func main() { http.Handle("/string", String("I'm a frayed knot.")) http.Handle("/struct", &Struct{"Hello", ":", "Gophers!"}) http.ListenAndServe("localhost:4000", nil) }
#62
package main import ( "code.google.com/p/go-tour/pic" "image" "image/color" ) type Image struct { Width int Height int } func (img *Image) ColorModel() color.Model { return color.RGBAModel } func (img *Image) Bounds() image.Rectangle { return image.Rect(0, 0, img.Width, img.Height) } func (img *Image) At(x, y int) color.Color { return color.RGBA{uint8(x * y), uint8(y - x), 255, 255} } func main() { m := &Image{100, 100} pic.ShowImage(m) }
#63
package main import ( "io" "os" "strings" ) type rot13Reader struct { r io.Reader } func (r *rot13Reader) Read(p []byte) (n int, err error) { n, err = r.r.Read(p) for i := range p { if ('A' <= p[i] && p[i] <= 'M') || ('a' <= p[i] && p[i] <= 'm') { p[i] += 13 } else if ('N' <= p[i] && p[i] <= 'Z') || ('n' <= p[i] && p[i] <= 'z') { p[i] -= 13 } } return } func main() { s := strings.NewReader( "Lbh penpxrq gur pbqr!") r := rot13Reader{s} io.Copy(os.Stdout, &r) }
#71
package main import ( "code.google.com/p/go-tour/tree" "fmt" ) // 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 == nil { return } Walk(t.Left, ch) ch <- t.Value Walk(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 func() { Walk(t1, c1) close(c1) }() go func() { Walk(t1, c2) close(c2) }() for { x, ok1 := <-c1 y, ok2 := <-c2 if !ok1 || !ok2 { return ok1 == ok2 } if x != y { return false } } return false } func main() { t := tree.New(1) ch := make(chan int) go func() { Walk(t, ch) close(ch) }() for i := range ch { fmt.Println(i) } if Same(tree.New(1), tree.New(1)) { fmt.Println("Same!") } if Same(tree.New(1), tree.New(2)) { fmt.Println("Not Same!") } }
#72
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) } // Crawl uses fetcher to recursively crawl // pages starting with url, to a maximum of depth. func Crawl(url string, depth int, fetcher Fetcher) { isFetchedByUrl := make(map[string]bool) crawl(url, depth, fetcher, isFetchedByUrl) return } func crawl(url string, depth int, fetcher Fetcher, isFetchedByUrl map[string]bool) { if depth <= 0 { return } if v, ok := isFetchedByUrl[url]; ok && v { return } body, urls, err := fetcher.Fetch(url) if err != nil { fmt.Println(err) return } fmt.Printf("found: %s %q\n", url, body) isFetchedByUrl[url] = true var wg sync.WaitGroup for _, u := range urls { wg.Add(1) go func(u string) { defer wg.Done() crawl(u, depth-1, fetcher, isFetchedByUrl) }(u) } wg.Wait() return } func main() { Crawl("http://golang.org/", 4, fetcher) } // 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{ "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/", }, }, }