1. Go入門
ver. 2017/04
The Go gopher was designed by Renee French.
The gopher stickers was made by Takuya Ueda.
Licensed under the Creative Commons 3.0
Attributions license.
23. 配列 −1−
[要素数]要素の型
型・メソッド・インタフェース/配列 −1−
23
var a [3]int
a[1] = 10
b := [...]int{1, 2, 3}
for i, n := range b {
fmt.Println(i,"/",len(b),"=>", n)
}
Playgroundで動かす
要素数が違えば別の型
...で初期値の要素に合わせる
添字と値で繰り返せる
24. 配列 −2−
値でコピーされる
型・メソッド・インタフェース/配列 −2−
24
a := [3]int{1, 2, 3}
b := a
a[0] = 10
for i := range a {
fmt.Println(a[i], b[i])
}
参照がコピーされる
わけではない
10, 1
2, 2
3, 3
関数に渡した場合も
同様に値がコピーされる
Playgroundで動かす
2つ目は省略可
25. スライス −1−
[]要素の型
make([]要素の型, 要素数[, キャパシティ])
型・メソッド・インタフェース/スライス −1−
25
a := make([]int, 3, 10)
fmt.Println(a, len(a), cap(a))
b := []int{1, 2, 3}
for i, n := range b {
fmt.Println(i,"/",len(b),"=>", n)
}
Playgroundで動かす
スライスでもrangeは使える
27. スライス −3−
append(スライス, 要素...) スライス
型・メソッド・インタフェース/スライス −3−
27
var a []int // nil
for i := 0; i <= 10; i++ {
a = append(a, i * 10)
fmt.Println(len(a), cap(a), a)
}
Playgroundで動かす
appendした際にcapを
超えた場合は
新しく配列が確保される
56. ゴールーチン間のデータ競合 −2−
ゴールーチン・チャネル/ゴールーチン間のデータ競合 −2−
56
n := 1
go func() {
for i := 2; i <= 5; i++ {
fmt.Println(n, "*", i)
n *= i
time.Sleep(100)
}
}()
http://play.golang.org/p/yqk82u0E4V
for i := 1; i <= 10; i++ {
fmt.Println(n, "+", i)
n += 1
time.Sleep(100)
}
競合
57. データ競合の解決
■ 問題点
● どのゴールーチンが先にアクセスするか分からない
● 値の変更や参照が競合する
■ 解決方法
● 1つの変数には1つのゴールーチンからアクセスする
● チャネルを使ってゴールーチン間で通信をする
● またはロックをとる(syncパッケージ)
ゴールーチン・チャネル/データ競合の解決
57
"Do not communicate by sharing memory; instead,
share memory by communicating"
84. go test
go test と testingパッケージ/go test
84
■ testを行うためコマンド
_testというサフィックスの付いた
goファイルを対象にしてテストを実行
# mypkgのテスト行う
$ go test mypkg
ok mypkg 0.007s
# 失敗する場合
$ go test mypkg
--- FAIL: TestHex_String (0.00s)
hex_test.go:11: expect="a"
actual="A"
FAIL
FAIL mypkg 0.008s
hex.go ⇒ hex_test.go
85. go testのオプション(一部)
■ -v
詳細を表示する。
■ -cpu
実行する並列度を指定する。
複数のコアを使ったテストができる。
■ -race
データの競合が起きないかテストする。
■ -cover
カバレッジを取得する。
go test と testingパッケージ/go testのオプション(一部)
85
86. testingパッケージ
■ テストを行うため機能を提供するパッケージ
*testing.T型のメソッド使う。
go test と testingパッケージ/testingパッケージ
86
package mypkg_test
import "testing"
import "mypkg"
func TestHex_String(t *testing.T) {
expect := "a"
actual := mypkg.Hex(10).String()
if actual != expect {
t.Errorf(`expect="%s" actual="%s"`, expect, actual)
}
}
type Hex int
func (h Hex) String() string {
return fmt.Sprintf("%x", int(h))
}
mypkg.go
mypkg_test.go
93. コンパイルエラーになるもの −1−
■ 型の不一致
go test と testingパッケージ/コンパイルエラーになるもの −1−
93
var n int = 100
var m float64 = 1.5
// エラー
var a int = n + m
// OK
var b int = n + int(m)
94. コンパイルエラーになるもの −2−
■ 未使用の変数/パッケージ
go test と testingパッケージ/コンパイルエラーになるもの −2−
94
import (
"fmt" // エラー
_ "io" // OK
)
func main() {
var n int = 100 // エラー
_ = 200 // OK
}
95. コンパイルエラーになるもの −3−
■ インタフェースの未実装(型の不一致)
go test と testingパッケージ/コンパイルエラーになるもの −3−
95
type Hex int
func (h Hex) Str() string {
return fmt.Sprintf("%x", int(h))
}
// エラー
var _ fmt.Stringer = Hex(100)
type Stringer
interface {
String() string
}
96. コンパイルエラーになるもの −4−
■ 曖昧な記述
go test と testingパッケージ/コンパイルエラーになるもの −4−
96
type Hoge struct{ N int }
type Piyo struct{ N int }
type Foo struct {
Hoge
Piyo
}
func main() {
f := Foo{Hoge{100}, Piyo{200}}
fmt.Println(f.N) // エラー
fmt.Println(f.Hoge.N) // OK
}
106. 変数に値を入れる
106
var n int
fmt.Println(n) // 0
vp := reflect.ValueOf(&n)
v := vp.Elem()
if v.CanSet() {
v.SetInt(100)
}
fmt.Println(n) // 100
http://play.golang.org/p/HkJPjQsP8o
リフレクション/変数に値を入れる