またtour of goをやったのでその中で覚えとこうと思ったとこだけメモりました。
本当にメモなので雑ですが。
いつのまにか全部日本語になっていて嬉しかったです。
目次
- 関数の引数は型が同じならまとめられる
- 関数は複数の戻り値を返せる
- 戻り値に名前をつけられる.宣言までしてくれる(慣れるまで読みづらそう)
- var は:で省略できる
- printの仕方
- 型変換は明示的にしなければならない
- constはnumeric 謎
- forとifに()いらない
- switch基本breakされる。したくなければfallthroughをcaseの最後につける
- swichに条件式かける
- deferはreturnの後に関数を呼ぶように予約することができる
- 複数deferはLIFO(last-in-first-out:最後に入れたのが最初に出る)で実行される
- &がポインタへのキャスト が値へのキャスト と覚える。型宣言の時はintとなるので注意
- 配列
- []に長さ指定しなければSliceになる
- sliceは配列への参照のようなもの
- sliceを作る時配列全部入れたいならa[:]がいいかな
- len(slice)が長さ。cap(slice)はsliceの最初の要素から元となる配列の末尾までの長さ
- slice nilでもlenとcapに0入る
- ていうかnullじゃなくてnilなのか
- makeでSliceの初期化
- SliceのSliceとかも作れる(二次元配列的な)
- Sliceに要素をたすにはappend(slice,要素)
- Range
- mapはDictionaryみたいなもん
- tryGetしなくてもバグらない
- closureよくわかんねえけど気をつけよう
- type hoge int で型を宣言できる。それにメソッドを持たせることもできる。
- 同じパッケージで宣言されている型にしかメソッド宣言できない。そりゃそうだ
- goは常に値渡し
- メソッドのレシーバーはポインタと型(?)で指定できる。インスタンスの内容を変更する場合はポインタじゃないとどうにもならない
- メソッド基本的にポインタレシーバで宣言する!!
- interfaceは明示的にimplementsしないでメソッドを実装しさえすればimplementsしてるとみなされる
- interfaceのメソッドをポインタレシーバで実装したら参照を使わないとエラー出る。。。引っかかりそう
- 空のinterface{}はObjectみたいなもの
- Type assertions 多分isからのasみたいなもん
- swichを使うと複数いける。あんま使って欲しくなさそう
- Stringersインターフェース String()メソッドを実装するとstringとして出力できる?
- Error() stringを実装すればerrorとして扱える
- Channels
- Select
- sync.Mutex
関数の引数は型が同じならまとめられる
1 2 3 4 |
func add(x, y int) int { return x + y } |
関数は複数の戻り値を返せる
戻り値に名前をつけられる.宣言までしてくれる(慣れるまで読みづらそう)
1 2 3 4 5 6 |
func split(sum int) (x, y int) { x = sum * 4 / 9 y = sum - x return } |
var は:で省略できる
var a = 2
a := 2
printの仕方
1 2 3 4 5 6 7 8 |
func main() { var i int var f float64 var b bool var s string fmt.Printf("%v %v %v %q", i, f, b, s) } |
型変換は明示的にしなければならない
キャストしないとエラーになる
1 2 3 4 |
i := 42 f := float64(i) u := uint(f) |
constはnumeric 謎
forとifに()いらない
switch基本breakされる。したくなければfallthroughをcaseの最後につける
swichに条件式かける
deferはreturnの後に関数を呼ぶように予約することができる
defer へ渡した関数の引数は、すぐに評価されますが、その関数自体は呼び出し元の関数がreturnするまで実行されません。
複数deferはLIFO(last-in-first-out:最後に入れたのが最初に出る)で実行される
&がポインタへのキャスト が値へのキャスト と覚える。型宣言の時はintとなるので注意
配列
1 2 3 |
primes := [6]int{2, 3, 5, 7, 11, 13} ve] |
===========Slice始まり============
[]に長さ指定しなければSliceになる
1 2 |
var s []int = 配列[1:4] |
sliceは配列への参照のようなもの
sliceを直接作ると配列を作ってからそれを参照するスライスを作成するようになっている
sliceを作る時配列全部入れたいならa[:]がいいかな
1 2 3 4 5 6 7 8 9 |
//以下の配列において var a [10]int //これらのスライス式は等価です: a[0:10] a[:10] a[0:] a[:] |
len(slice)が長さ。cap(slice)はsliceの最初の要素から元となる配列の末尾までの長さ
slice nilでもlenとcapに0入る
ていうかnullじゃなくてnilなのか
makeでSliceの初期化
1 2 |
b := make([]int, 0, 5) // len(b)=0, cap(b)=5 |
SliceのSliceとかも作れる(二次元配列的な)
Sliceに要素をたすにはappend(slice,要素)
cap超えたら倍の配列を割り当て直す(Listと同じだね)
nilのsliceにも追加できる
===========slice終わり============
Range
1 2 3 4 5 6 |
var pow = []int{1, 2, 4, 8, 16, 32, 64, 128} for i, v := range pow { fmt.Printf("2**%d = %d\n", i, v) } //iはインデックスvは要素のコピー |
===========mapはじまり============
mapはDictionaryみたいなもん
tryGetしなくてもバグらない
1 2 |
v, ok := m["Answer"] |
===========map終わり============
closureよくわかんねえけど気をつけよう
type hoge int で型を宣言できる。それにメソッドを持たせることもできる。
同じパッケージで宣言されている型にしかメソッド宣言できない。そりゃそうだ
goは常に値渡し
メソッドのレシーバーはポインタと型(?)で指定できる。インスタンスの内容を変更する場合はポインタじゃないとどうにもならない
メソッド基本的にポインタレシーバで宣言する!!
interfaceは明示的にimplementsしないでメソッドを実装しさえすればimplementsしてるとみなされる
interfaceのメソッドをポインタレシーバで実装したら参照を使わないとエラー出る。。。引っかかりそう
空のinterface{}はObjectみたいなもの
Type assertions 多分isからのasみたいなもん
1 2 3 4 |
var i interface{} = "hello" s,ok := i.(string) fmt.Println(s) |
swichを使うと複数いける。あんま使って欲しくなさそう
1 2 3 4 5 6 7 8 9 |
switch v := i.(type) { case T: // here v has type T case S: // here v has type S default: // no match; here v has the same type as i } |
Stringersインターフェース String()メソッドを実装するとstringとして出力できる?
Error() stringを実装すればerrorとして扱える
Channels
1 2 3 4 5 6 7 8 9 10 11 |
ch := make(chan int) //みたいに宣言 chan int で多分型なので注意(初見だと読みづらい) //こう使う ch <- v // v をチャネル ch へ送信する v := <-ch // ch から受信した変数を v へ割り当てる //イメージ的にはキューにgoroutineを詰めてる感じ //ch <-で詰めたgoroutineが全て終わらなければ <-ch は呼ばれない //詰めたより多く<-chするとエラーが出る |
バッファとしてもよく使いそうだな〜しんどい
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package main import ( "fmt" ) func fibonacci(n int, c chan int) { x, y := 0, 1 for i := 0; i < n; i++ { c <- x x, y = y, x+y } //close しないとmain()のforで一生回るのでnull的なエラーが出る close(c) } func main() { c := make(chan int, 10) go fibonacci(cap(c), c) for i := range c { fmt.Println(i) } } |
Select
これは便利だ〜
channelが準備できるまで待って準備できたのから実行してくれる。複数準備できてたらランダム実行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
package main import "fmt" import "time" func fibonacci(c, quit chan int) { x, y := 0, 1 for { time.Sleep(1 * time.Second) // 1秒待つ select { case c <- x: fmt.Println("case c") x, y = y, x+y case <-quit: fmt.Println("quit") return } } } func main() { c := make(chan int) quit := make(chan int) go func() { fmt.Println("func") for i := 0; i < 10; i++ { fmt.Println("funcの方",<-c) } quit <- 0 }() fmt.Println("fibo前") fibonacci(c, quit) } |
こういう使い方もできるticktとafterhはchを返すんだね
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package main import ( "fmt" "time" ) func main() { tick := time.Tick(100 * time.Millisecond) boom := time.After(500 * time.Millisecond) for { select { case <-tick: fmt.Println("tick.%T",tick) case <-boom: fmt.Println("BOOM!") return default: fmt.Println(" .") time.Sleep(50 * time.Millisecond) } } } |
sync.Mutex
Lock して居るうちは他からアクセスできない
そのうち気が向けば綺麗にまとめたいね。
それにしてもgoroutineとかselectとかchannelとかは使いようによってはものすごく便利そうですね。
素敵。ではまた。