Go
業務でGoをやることとなりそうだ、勉強しなくては。。。
ということでGoの入門として、A Tour of Goやっていきます。
演習問題をひたすら解いていく
Exercise: Loops and Functions
- 引数の平方根に近い値を返却する
平方根を求めるためのループ回数は10回固定
- 引数の平方根に一致した時の値とループ回数を返却する
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
stringで渡される文の、各単語の出現回数を数える
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
フィボナッチ数を返却するクロージャを返す
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
IPAddr型を実装して、IPアドレスを出力する時の表記を作成する
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
ROT13換字式暗号を変換する
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で見せてもらった時は速かったので実行環境が悪いだけだと思うが。。。)