Go言語のTips¶
今日の GoCon で学んだこと。 (順次更新していきます)
Sliceの扱い方¶
// slice作成 第二引数は初期の大きさ
urls := make([]Target, 0)
// 追加するにはappendを使う
urls = append(urls, Target{"http://tdoc.info/blog/", "setAccount"})
// 順々にアクセス
for i, u := range urls{ // iはindex番号。0から始まる
fmt.Println(i, u)
}
チャンネルのタイムアウト¶
time.Afterを使う。
for {
select {
case receive := <-receiver:
log.Println(receive)
case <-time.After(time.Second):
log.Println("timeout")
return
}
}
goroutineの数を制限する¶
まだ理解不足…
func worker(msg string) <-chan string {
limit := make(chan int, 5) // limitを指定
receiver := make(chan string)
for i := 0; i < 1000; i++ {
go func(i int) {
limit <- 1
msg := fmt.Sprintf("%d %s done", i, msg)
receiver <- msg
<-limit
}(i)
}
return receiver
}
testの仕方¶
type Dummy struct {
x int
y int
}
func (d *Dummy) Testing() int { return d.x + d.y }
という感じで main.go の中で定義しておく。
んで、 main_test.go というファイル名で以下のように書く。今回は同じ mainパッケージなので、package宣言はmainで。これにより、Dummy型がなにも 付けなくても呼べる。
package main
import (
"testing"
)
func TestTarget(t *testing.T) {
d := Dummy{1, 2}
if 3 != d.Testing() {
t.Fail() // テストする
}
}
testingパッケージをimportしておいて、あと、関数は Test ではじめるこ と。引数に *testing.T を渡さられるので、そいつでFailとかを起こす。
assertとかはないみたい。
あとはgo testで実行。
% go test
PASS
ok _/home/example/Works/golang/multihttp 0.007s
# -vをつけると個々のtest名が出てくる
%go test -v
=== RUN TestTarget
--- PASS: TestTarget (0.00 seconds)
PASS
ok _/home/example/Works/golang/multihttp 0.007s
あとは -p n をつけると並列で、 -cpu n とつけると指定したCPU数を使っ てくれるみたい。
Example¶
また、Exampleというテストもかける。これは標準出力の文字列をテストする もの。
func ExampleHello() {
fmt.Println("hello, and")
fmt.Println("goodbye")
// Output:
// hello, and
// goodbye
}
という感じで、main_test.goの中に Example で関数名で始まるように書いてお くと、go testでテストされる。この場合、Printlnが標準出力に出す"hello, and(改行)goodbye"と、 // Output: というコメントの内容とが比較される。
ベンチマーク¶
同じようにベンチマークも書ける。BenchMarkで始まる関数を定義して
func BenchmarkHello(b *testing.B) {
for i := 0; i < b.N; i++ { // b.Nで指定できる
fmt.Sprintf("hello")
}
}
-bench をつけてgo testを実行してみる。
% go test -bench Hello
PASS
BenchmarkHello 5000000 373 ns/op
ok _/home/shirou/Works/golang/multihttp 2.218s
benchの後にパターンを指定して、そのパターンに適合したベンチマークだけが実行される。
benchcmp ってのがついてくるのでそれで比較もできる。
エラー処理¶
こんな感じでerrを返すように関数を書いておくのが流儀。
if val, err := Get(); err != nil{
// エラーハンドリング
}
caseの中にも式が書ける¶
func unhex(c byte) byte {
switch {
case '0' <= c && c <= '9':
return c - '0'
case 'a' <= c && c <= 'f':
return c - 'a' + 10
case 'A' <= c && c <= 'F':
return c - 'A' + 10
}
return 0
}
anonymous fields¶
フィールド名を匿名にしとくと簡単に書けますよ、というお話。
type Car struct {Color string}
type PricedCar struct { // Carを内包している
Car // 変数名なし
Price string
}
car := PricedCar{Car{Color: "green"}, "100万円"}
fmt.Println(car.Color) // car.Car.Colorじゃない
goroutineの待ち合わせ¶
syncパッケージを使うと楽。
func main() {
var wg sync.WaitGroup
for i:=0; i<3; i++ {
wg.Add(1) // 待ち合わせる数を増やしていく
go func(i int) {
log.Println(i)
wg.Done() // 終わった数
}(i)
}
wg.Wait() // ここで待つ
}
Comments
comments powered by Disqus