A Tour of Goの問題を少し解いてみる

# Go
業務でGoをやることとなりそうだ、勉強しなくては。。。
ということでGoの入門として、[A Tour of Go](https://go-tour-jp.appspot.com/welcome/1)やっていきます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/132609/38403d39-de54-9812-fab9-38b5c3ab4634.png)

# 演習問題をひたすら解いていく

## [Exercise: Loops and Functions](https://go-tour-jp.appspot.com/flowcontrol/8)

- 引数の平方根に近い値を返却する

平方根を求めるためのループ回数は10回固定

- 引数の平方根に一致した時の値とループ回数を返却する


```go
package main

import (
	"fmt"
	"math"
)

func Sqrt(x float64) float64 {
	z := 1.0
	for i := 0; i < 10; i++ {
		z -= (z * z - x) / (2 * z)
	}
	return z
}

func SqrtCount(x float64) (float64, int) {
	z := 1.0
	sqrt := math.Sqrt(x)
	count := 0
	for ; z != sqrt; count++ {
		z -= (z * z - x) / (2 * z)
	}
	return z, count
}

func main() {
	fmt.Printf("Sqrt : %v\n", Sqrt(2))
	fmt.Printf("math.Sqrt : %v\n", math.Sqrt(2))
	value, count := SqrtCount(2)
	fmt.Printf("SqrtCount : %v(%d回ループ)\n", value, count)
}
```

実行結果

```
Sqrt : 1.414213562373095
math.Sqrt : 1.4142135623730951
SqrtCount : 1.4142135623730951(5回ループ)
```

## [Exercise: Maps](https://go-tour-jp.appspot.com/moretypes/23)

stringで渡される文の、各単語の出現回数を数える

```go
package main

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

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

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

実行結果

```
PASS
 f("I am learning Go!") = 
  map[string]int{"Go!":1, "I":1, "am":1, "learning":1}
PASS
 f("The quick brown fox jumped over the lazy dog.") = 
  map[string]int{"quick":1, "brown":1, "jumped":1, "the":1, "The":1, "over":1, "lazy":1, "dog.":1, "fox":1}
PASS
 f("I ate a donut. Then I ate another donut.") = 
  map[string]int{"another":1, "I":2, "ate":2, "a":1, "donut.":2, "Then":1}
PASS
 f("A man a plan a canal panama.") = 
  map[string]int{"A":1, "man":1, "a":2, "plan":1, "canal":1, "panama.":1}
```

## [Exercise: Fibonacci closure](https://go-tour-jp.appspot.com/moretypes/26)

フィボナッチ数を返却するクロージャを返す

```go

package main

import "fmt"

func fibonacci() func() int {
	a,b,c := 0,0,1
	return func () int {
		a, b, c = b, c, b + c
		return a
	}
}

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

実行結果

```
0
1
1
2
3
5
8
13
21
34
```

## [Exercise: Stringers](https://go-tour-jp.appspot.com/methods/18)

IPAddr型を実装して、IPアドレスを出力する時の表記を作成する

```go
package main

import "fmt"

type IPAddr [4]byte

func (i IPAddr) String() string {
	return fmt.Sprintf("%d.%d.%d.%d", i[0], i[1], i[2], i[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)
	}
}
```

出力結果

```
loopback: 127.0.0.1
googleDNS: 8.8.8.8
```

## [Exercise: rot13Reader](https://go-tour-jp.appspot.com/methods/23)

ROT13換字式暗号を変換する

```go
package main

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

type rot13Reader struct {
	r io.Reader
}

func (rot rot13Reader) Read (b []byte) (int, error) {
	num, err := rot.r.Read(b)

	if err != nil {
		return num, err
	}

	for i := 0; i < num; i++ {
		if ('a' <= b[i] && b[i] <= 'm') || ('A' <= b[i] && b[i] <= 'M'){
			b[i] += 13
		} else if ('n' <= b[i] && b[i] <= 'z') || ('N' <= b[i] && b[i] <= 'Z') {
			b[i] -= 13
		}
	}
	return num, err
}

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

出力結果

```
You cracked the code!
```

# 所感

- 書いていてポインタがあったり、複数の値を返却できたりと書きやすいところが多い。
- goroutine, channelがあって並列処理とかも楽に書けそう。
- 調べる限りだとコンパイルが速いと書いてあったが、そこまで速さが実感できなかった。(他PCで見せてもらった時は速かったので実行環境が悪いだけだと思うが。。。)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/132609/aaf3e30d-5317-7500-c7d4-e035942b3e67.png)