Golang学習
Go言語を学習する上で忘れそうなことや気になる点をメモしていく予定。
変数や関数の引数は型が同じ場合は省略できる。
// var a int, b int と同じ
var a, b int
// func add(x int, y int) int と同じ
func add(x, y int) int {
return x + y
}
for
ループで初期化と後処理が不要ならセミコロンは省略できる。
var i = 0
for i < 10 {
i++
}
if
文にも初期化が書ける。
if b := a * a; b < 10 {
fmt.Println(b)
}
便利そうな気はする。
Go言語のswitch
はfall throughされない。
defer
は渡した関数の評価は遅延させるけれど引数の評価は先に行うらしい。
func run() {
defer foo(bar())
baz()
}
func foo(s string) {
fmt.Println(s)
}
func bar() string {
fmt.Println("bar")
return "foo"
}
func baz() {
fmt.Println("baz")
}
このコードを実行するとbar
、baz
、foo
の順に出力される。
defer
を複数書いた場合、LIFOの順に実行される。
外部リソースの解放に使えそう。
type
でstruct
に名前を付けるのは単なるエイリアスっぽい。
構造が同じなら同じ型とみなしているっぽい。
type Point struct {
x int
y int
}
a := Point{2, 3}
var b Point = Point{2, 3}
var c struct {
x int
y int
} = Point{2, 3}
var d Point = struct {
x int
y int
}{2, 3}
var e struct {
x int
y int
} = struct {
x int
y int
}{2, 3}
と思ったけど同じ構造で異なる2つのtype
を定義した場合、代入はできなかった。
type AlterPoint struct {
x int
y int
}
var f Point = AlterPoint{2, 3}
次のようなエラーになった。
cannot use AlterPoint{...} (type AlterPoint) as type Point in assignment
ルールがよくわからないな。
配列やスライスをイテレートする場合はfor
とrange
を使う。
foobar := []string{"foo", "bar"}
for i, s := range foobar {
fmt.Println(i, s)
}
range
はfor
と組み合わせるためのキーワードなだけで特にイテレーター的な何かを返す汎用的なやつというわけではなさそうなので変数に代入とかはできない。
r := range foobar
syntax error: unexpected range, expecting expression
make
関数でスライスを作れる。
xs := make([]int, 5)
fmt.Println(xs) //[0 0 0 0 0]
for i := range xs {
xs[i] = i * i
}
fmt.Println(xs) //[0 1 4 9 16]
マップ。
var m1 map[string]int = map[string]int{
"foo": 1,
"bar": 2,
}
fmt.Println(m1)
m1["baz"] = 3
fmt.Println(m1)
//makeで初期化もできる
m2 := make(map[string]int)
m2["foo"] = 1
m2["bar"] = 2
fmt.Println(m2)
//structのようにtypeで名前を付けられる
type M3 map[string]int
m3 := M3{
"foo": 1,
"bar": 2,
}
fmt.Println(m3)
// // これもstructのときと同じく異なる名前同士だと代入できない
// // > cannot use M3{...} (type M3) as type M4 in assignment
// type M4 map[string]int
// var m4 M4 = M3{
// "foo": 1,
// "bar": 2,
// }
変数宣言・初期化時の:=
とfor
ループの:=
は同じものなのかな?
次の2つは同じ意味だと理解してる。
i := 0
var i int = 0
でも次のfor
ループを、
for i := 0; i < 3; i++ {
fmt.Println(i)
}
次のようには書けない。
for var i int = 0; i < 3; i++ {
fmt.Println(i)
}
syntax error: var declaration not allowed in for initializer
このようなエラーになる。
そのためi := 0
はvar i int = 0
の糖衣構文ではなさそう。
var foo = "hello"
var bar = 123
と書けるところを、
var (
foo = "hello"
bar = 123
)
と書けるようだけど、この糖衣構文にはどんなメリットがあるんだろう?
単に何度もvar
を書かなくていいよ、ということかな。
複数の変数や引数を宣言するとき、型が同じ場合に最後以外を省略できる仕様と同じ雰囲気を感じてる。