# 要約

"Go"lden weekなのでGo入門としてA tour of Go
やった。
exerciseで書いたやつ。

## やった環境

```% go version
go version go1.10.1 darwin/amd64
```

## Flow control statements: for, if, else, switch and defer

### sqrt

exercise-loops-and-functions.go
```package main

import (
"fmt"
"math"
)

func Sqrt(x float64) (z float64) {
z = 1
for {
if y := z - (z*z-x)/(2*z); math.Abs(z-y) < 1e-14 {
break
} else {
z = y
}
}
return
}

func main() {
for i := 1; i < 1000; i++ {
fmt.Printf("i: %v\n", i)
fmt.Println(Sqrt(float64(i)))
fmt.Println(math.Sqrt(float64(i)))
}
}

```

## More types: structs, slices, and maps.

### slice

exercise-slices.go
```package main

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

func Pic(dx, dy int) [][]uint8 {
ret := make([][]uint8, dy)
for i := range ret{
ret[i] = make([]uint8, dx)
for j := range ret[i]{
//          ret[i][j] = uint8((i+j/2))
//          ret[i][j] = uint8((i*j))
ret[i][j] = uint8((i^j))
}
}
return ret
}

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

```

### map

exercise-maps.go
```package main

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

func WordCount(s string) map[string]int {
splitted := strings.Split(s, " ")
x := make(map[string]int)
for _,v := range splitted {
x[v] += 1
}
return x
}

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

### fibonacci

exercise-fibonacci-closure.go
```package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
a, b := -1, 1
return func() int {
a, b = b, a+b
return b
}
}

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

## Methods and interfaces

### stringer

exercise-stringer.go
```package main

import "fmt"

func (ip IPAddr) String() string {
return fmt.Sprintf("%v.%v.%v.%v", ip[0], ip[1], ip[2], ip[3])
}

func main() {
"loopback":  {127, 0, 0, 1},
}
for name, ip := range hosts {
fmt.Printf("%v: %v\n", name, ip)
}
}
```

### errorを返す

exercise-errors.go
```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 0, ErrNegativeSqrt(x)
}
z := float64(1)
for {
if y := z - (z*z-x)/(2*z); math.Abs(z-y) < 1e-14 {
break
} else {
z = y
}
}
return z, nil
}
func main() {
fmt.Println(Sqrt(2))
fmt.Println(Sqrt(-2))
}
```

```package main

for i:= 0; i<len(x); i++{
x[i] = byte('A')
}
return len(x), nil
}

func main() {
}
```

```package main

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

}

ranges := [][]byte{
[]byte{'A', 'Z'},
[]byte{'a', 'z'},
}
for _, lr := range ranges{
if lr[0] <= x && x <= lr[1]{
if y := x - 13; y < lr[0]{
return y + 26
}else{
return y
}
}
}
return x
}

if err != nil{
return 0, err
}
for i := 0; i < n; i++ {
x[i] = rot.decode(x[i])
}
return n, nil
}

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

# imageかくやつ

exercise-images.go
```package main

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

type Image struct{
w,h int
}

func (img Image)Bounds()image.Rectangle{
return image.Rect(0,0,img.w, img.h)
}

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

func (img Image)At(x, y int)color.Color{
v := uint8(x^y)
return color.RGBA{v,v,255,255}
}

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

```

## Concurrency

### 2分木が同じ列を保持してるかどうか

exercise-equivalent-binary-trees.go
```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 == nil {
return
}
Walk(t.Left, ch)
ch <- t.Value
Walk(t.Right, ch)
}

func TestWalk() string {
for elm := 0; elm < 10; elm++ {
ch := make(chan int)
go Walk(tree.New(elm), ch)

for i := 1; i < 11; i++ {
if elm*i != <-ch{
return "ng"
}
}
}
return "ok"
}

// Same determines whether the trees
// t1 and t2 contain the same values.
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 TestSame() string {
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
if Same(tree.New(i), tree.New(j)) != (i == j) {
return "ng"
}
}
}
return "ok"
}

func main() {
fmt.Println(TestWalk())
fmt.Println(TestSame())
}
```

### fetchを並列にする+同じアドレスをfetchしないみたいなやつ

exercise-web-crawler.go
```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 {
urls map[string]bool
mux  sync.Mutex
}

func (c *Cache) exist(url string) bool {
c.mux.Lock()
defer c.mux.Unlock()
defer func() { c.urls[url] = true }()
return c.urls[url]
}

func Crawler(url string, depth int, fetcher Fetcher, cache *Cache, c chan bool) {
defer func() { c <- true }()
if depth <= 0 {
return
}
if cache.exist(url) {
return
}
body, urls, err := fetcher.Fetch(url)

if err != nil {
fmt.Println(err)
return
}

fmt.Printf("found: %s %q\n", url, body)
ch := make(chan bool, len(urls))
for _, u := range urls {
go Crawler(u, depth-1, fetcher, cache, ch)
}
for i := 0; i < len(urls); i++ {
_ = <-ch
}
return
}

// Crawl uses fetcher to recursively crawl
// pages starting with url, to a maximum of depth.
func Crawl(url string, depth int, fetcher Fetcher) {
// TODO: Fetch URLs in parallel.
// TODO: Don't fetch the same URL twice.
// This implementation doesn't do either:
cache := Cache{urls: make(map[string]bool)}
c := make(chan bool, 1)
Crawler(url, depth, fetcher, &cache, c)
_ = <-c
}

func main() {

Crawl("https://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
}
}

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

```