また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
関数の引数は型が同じならまとめられる#
func add(x, y int) int {
return x + y
}
関数は複数の戻り値を返せる#
戻り値に名前をつけられる.宣言までしてくれる(慣れるまで読みづらそう)#
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
var は:で省略できる#
var a = 2
a := 2
printの仕方#
func main() {
var i int
var f float64
var b bool
var s string
fmt.Printf("%v %v %v %q", i, f, b, s)
}
型変換は明示的にしなければならない#
キャストしないとエラーになる
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となるので注意#
配列#
primes := [6]int{2, 3, 5, 7, 11, 13}
ve]
===========Slice始まり============
[]に長さ指定しなければSliceになる#
var s []int = 配列[1:4]
sliceは配列への参照のようなもの#
sliceを直接作ると配列を作ってからそれを参照するスライスを作成するようになっている
sliceを作る時配列全部入れたいならa[:]がいいかな#
//以下の配列において
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の初期化#
b := make([]int, 0, 5) // len(b)=0, cap(b)=5
SliceのSliceとかも作れる(二次元配列的な)#
Sliceに要素をたすにはappend(slice,要素)#
cap超えたら倍の配列を割り当て直す(Listと同じだね)
nilのsliceにも追加できる
===========slice終わり============
Range#
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しなくてもバグらない#
v, ok := m["Answer"]
===========map終わり============
closureよくわかんねえけど気をつけよう#
type hoge int で型を宣言できる。それにメソッドを持たせることもできる。#
同じパッケージで宣言されている型にしかメソッド宣言できない。そりゃそうだ#
goは常に値渡し#
メソッドのレシーバーはポインタと型(?)で指定できる。インスタンスの内容を変更する場合はポインタじゃないとどうにもならない#
メソッド基本的にポインタレシーバで宣言する!!#
interfaceは明示的にimplementsしないでメソッドを実装しさえすればimplementsしてるとみなされる#
interfaceのメソッドをポインタレシーバで実装したら参照を使わないとエラー出る。。。引っかかりそう#
空のinterface{}はObjectみたいなもの#
Type assertions 多分isからのasみたいなもん#
var i interface{} = "hello"
s,ok := i.(string)
fmt.Println(s)
swichを使うと複数いける。あんま使って欲しくなさそう#
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#
ch := make(chan int)
//みたいに宣言 chan int で多分型なので注意(初見だと読みづらい)
//こう使う
ch <- v // v をチャネル ch へ送信する
v := <-ch // ch から受信した変数を v へ割り当てる
//イメージ的にはキューにgoroutineを詰めてる感じ
//ch <-で詰めたgoroutineが全て終わらなければ <-ch は呼ばれない
//詰めたより多く<-chするとエラーが出る
バッファとしてもよく使いそうだな〜しんどい
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が準備できるまで待って準備できたのから実行してくれる。複数準備できてたらランダム実行
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を返すんだね
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とかは使いようによってはものすごく便利そうですね。
素敵。ではまた。