Open13

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)
}

便利そうな気はする。

うらがみうらがみ

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")
}

このコードを実行するとbarbazfooの順に出力される。

うらがみうらがみ

deferを複数書いた場合、LIFOの順に実行される。

外部リソースの解放に使えそう。

うらがみうらがみ

typestructに名前を付けるのは単なるエイリアスっぽい。
構造が同じなら同じ型とみなしているっぽい。

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

ルールがよくわからないな。

うらがみうらがみ

配列やスライスをイテレートする場合はforrangeを使う。

foobar := []string{"foo", "bar"}
for i, s := range foobar {
  fmt.Println(i, s)
}

rangeforと組み合わせるためのキーワードなだけで特にイテレーター的な何かを返す汎用的なやつというわけではなさそうなので変数に代入とかはできない。

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 := 0var i int = 0の糖衣構文ではなさそう。

うらがみうらがみ
var foo = "hello"
var bar = 123

と書けるところを、

var (
  foo = "hello"
  bar = 123
)

と書けるようだけど、この糖衣構文にはどんなメリットがあるんだろう?

単に何度もvarを書かなくていいよ、ということかな。
複数の変数や引数を宣言するとき、型が同じ場合に最後以外を省略できる仕様と同じ雰囲気を感じてる。