Gopher道場 #1 受講メモ

2018年4月12日に開催されたメルペイ主催の「Gopher道場」の受講メモ。 復習も兼ねて公式ドキュメント等へのリンクを追記しました。

init関数は複数あってもおk

  • 全体で一つしか認めないとでかいinit.goになってしまう
  • 同一ファイルに複数あってもよい
  • 明示的に init() のように呼び出すことはNG
  • 実行される順序はtenntenn氏のQiita記事参照

  • initの中でgo routine呼べるか

    • 可能ではある(が状態管理に失敗すると積む)

行末にセミコロンを補う仕様がある

以前のバージョンではセミコロンを補った状態でコンパイラのエラーが表示されることがあったそう。 詳細は言語仕様 The Go Programming Language Specification - The Go Programming Language を確認。JavaScriptでもセミコロンの自動挿入は罠ですね。

配列とスライス、マップの扱い

リテラルが似てるので注意

[...]int{1, 2, 3} は配列 []int{1, 2, 3} はスライス。

  • 配列は値コピーでスライスは参照コピーされる違いがある。
  • 配列に追加する要素の数が初めから分かっていたら、あらかじめcapacityを確保しておく
    • capacity不足になったときに順次メモリが拡張されるため。

要素の操作

  • スライスに対する append : スライスがnilもおk。A Tour of Go の15ページ目に例がある。

    • 一方で nilのMapにappend: NG、空のオブジェクトを作る必要がある。
  • Mapの for range は取り出される順序は保障されないし、Go1.3から積極的に乱すようになった

  • Mapを値コピーしたい

    • 標準の関数にはないので手でやる必要がある
  • スライスは標準のcopyでおk

エイリアス

  • 用途:(GAEの)リファクタリングにおいて、contextが準標準パッケージ→標準パッケージへ移動したのでそれの移行のため。
  • 一時「直交する機能とはなんだったのか」とIssueが炎上……

戻り値

名前付戻り値

複数戻り値

  • 自作の関数だと複数戻り値の一部を捨てることはできないけど、mapの値取得でok省略できるのはどうして
    • 特別に扱われているから(for range の i, vv を無視できるのも同じですね)

定数

定数は書きやすさ優先で、型やキャストを意識させすぎないようにしている

10 * time.Second をDuration * Duration にキャストしなくていい。 変数に代入しようとした時点で int, float, string, bool, ... になる

クラス型オブジェクト指向との違い

  • 構造体でなくても、組み込み型でも新しい型を定義すればメソッドのレシーバになれる
  • スライスや配列もOK
  • ベクトルを扱うために配列にメソッドつけることもある

スコープ

  • Fileスコープってどういうこと?→import文の有効範囲がそのファイル内に閉じていること
  • Universeスコープは?組み込みの値が定義されている空間
    • true, falseキーワードではなく、代入可能なので true := falseも(言語仕様上は)おk
    • ECMAScript5より前の仕様で undefinedに代入可能だったのに似てる

defer

  • リソースの開放は defer を使うことが多い
  • deferの引数は呼んだ時点で評価された値が使われるので、defer文の後に書き換えても書き換わらない