Closed22
Go言語に触れる
下記スライドを参考にする。
特徴
- シンプルな文法
- 並行プログラミング
- シングルバイナリ
- クロスコンパイル
- ビルドが速い
- 並行処理とガベージコレクタを同時に採用
公式のプレイグラウンド
並行プログラミング
- ゴールーチン:軽量なスレッドのようなもの
- チャネル:ゴールーチン間で安全にデータをやり取りできる
txtar(テキストアーカイブ)形式:-- ファイルパス --
の形式で別ファイルとして記述できる。
- main パッケージの main プログラムから実行される。
- 実行前に初期化処理がある。
- ライブラリはモジュール単位で管理され、モジュールは複数のパッケージからなる。
-
&変数名
でポインタを参照する。 -
fmt
パッケージのプリントの使い方が色々あるので、知りたいときはドキュメントを参照する。
標準パッケージ一覧
関数内部で var
を省略して変数を定義出来る。
例: foo := "foo"
組み込み型
-
any
はinterface {}
の型エイリアス -
comparable
は型制約のみに使えるインタフェース(ジェネリクス)
ルーンリテラル:シングルクォートで一文字を囲む定数。
-
const
で定数を定義出来る。
なぜ型なしの定数が必要か
iota
- 列挙体のように利用する。
- 値に意味がある場合やデータベースに保存する値には利用しない。
ビット演算はどのような時に利用するのか。
-
&^
論理積の否定:!(A && B)
と同様? -
<-
チャネル演算 -
switch
分に式が利用できる。 - 乱数は
rand
で生成する。-
rand.Seed()
で元になる数値を指定する必要がある。 - シードに利用した値が同じであれば結果も同じ。
- そのため、現在時間を利用して乱数を生成することが多い。
-
rand.Intn(10)
で 0 から 10 までの整数で乱数を生成できる。
-
println
と fmt.Println
の違いが分からない。
- 構造体・配列のゼロ値はフィールド・要素が 0 になる。
- map の型が分からない
map[string]int
- 構造体は JavaScript のオブジェクトに近い。
- 配列は要素数を指定することが可能。要素数は変更出来ない。
-
{}
で囲んで配列リテラルを定義する。 -
[...]int
のように型リテラルで要素数を指定しないと、配列リテラルから要素数を推測する。
-
- スライスを作成する
make
は長さと容量を指定出来る。- 容量超える数の要素を
append
で追加しても容量は自動的に大きくなる。- 正確には新たに大きくなった容量のアドレスをメモリ上で確保する。
- 元のスライスへの参照が切れる。
- おおよそ元の容量の2倍の容量を確保する。
- 正確には新たに大きくなった容量のアドレスをメモリ上で確保する。
- 容量超える数の要素を
- スライスにはベースとなる配列が存在している。
- Slice Tricks というハック的な方法でスライスの要素のカット・削除などが出来る。
-
x/exp/slices
というパッケージを利用する方がシンプルに記述出来る。(標準パッケージに入る可能性がある)
-
- マップのキーを指定したアクセスを変数に代入するとき、2つ目の変数に存在しているかが返ってくる。
- 例:
n, ok := m["z"]
のok
- 例:
- 構造体のキーへのアクセスは
s.key
、マップのキーへのアクセスはm["key"]
。
- ユーザー定義型と型エイリアスを混同しないように注意する。
- ユーザー定義型:
type MyInt int
-
int
をベースにして新しい型を定義する?
-
- 型エイリアス:
type Applicant = http.Client
- 完全に同じ型、キャスト不要。
- 型名を出力すると元の型名が表示される。
fmt.Printf("%T", MyTypeAlias{})
- ユーザー定義型:
- 関数で複数の戻り値を返すことができる。
- 関数はファーストクラスオブジェクトらしい。
- 関数外の変数を参照しているときは注意が必要そう。JavaScript とは挙動が異なる。
- JavaScript と Go では変数を評価するタイミングが異なる?
- JavaScript の例(クロージャ作成時?):https://codesandbox.io/embed/js-playground-forked-9vy0fl?fontsize=14&hidenavigation=1&theme=dark
- Go の例(クロージャ実行時?):https://go.dev/play/p/dbKj1cZg_1f
- スライス内の関数を実行するタイミングでは
i
が2
になるため、全ての実行結果が2
になる。
- スライス内の関数を実行するタイミングでは
- JavaScript と Go では変数を評価するタイミングが異なる?
- 代入するとコピーが発生する。コピーは代入後の値に変更を加えても代入前の値に影響はない。
- メソッドでデータに対する操作を定義出来る。
- メソッドに関連づけられた変数をレシーバという。
- ポインタ型は破壊的変更を加えたいときに利用する?
- ポインタ型のメソッドリストは注意が必要。
-
*T
型はT
のメソッドも自身のメソッドとして扱われるらしい。 - ポインタ型でなければレシーバに変更を加えることはない。
-
- メソッド値とメソッド式がある。
- 具体的な値が注入されているかどうかの違い?
- メソッド値は値からメソッドを参照する。
- 例:
hex.string
- 例:
- メソッド式は型からメソッドを参照する。
- 例:
Hex.String
- 例:
パッケージ
- 先頭を大文字にした識別子が export される。
- ライブラリは main 関数が存在しないプログラム。export されたものを利用する。
-
go mod init モジュール名
でモジュールを初期化する。 -
go mod tidy
で利用していないモジュールの削除、利用されているモジュールのインポート?などを行う。 -
go mod edit -replace example.com/greetings=../greetings
で特定のモジュールの参照先を変更する。
スコープ
- レキシカルスコープ(定義した時点でスコープが決まる)を採用。
- ブロックスコープ
- 関数や if , for などのブロック内のスコープ。
- ファイルスコープ
- パッケージスコープ
- 関数間で変数を共有する方法:https://play.golang.org/p/iv6oVJRkWND
- ユニバーススコープ
- 組み込み型、組み込み関数を保持するスコープ。
パッケージの初期化
- init 関数で行う。
- 実行順がシビアなものは init 関数には記述しない。
- エラーハンドリングが必要な処理も書かない。
- init 関数は明示的に呼び出せない。
ライブラリ
-
go get
でライブラリを取得する。-u
でダウンロードを強制。 -
Go modules (vgo)
でモジュールという単位でバージョン管理を行う。- 互換性がなくなる場合はインポートパスを変更する。
- 可能な限り古いバージョンがインストールされる。
コマンドラインツール
-
os.Args
でコマンドラインの引数を取得する。-
flag.Args()
でも取得できる。
-
-
flag
でオプション(-
で始まる)を便利に扱うことが可能。-
init
関数で事前の処理として変数を初期化することが可能。 -
flag.Parse()
で実際に値が設定される。
-
入出力
-
fmt.Fprintln
:異常系の出力先を指定して出力できる。- 出力先は
os.Stderr
、os.Stdout
などがある。
- 出力先は
-
os.Exit(0)
:プログラムを終了する。(正常系?)- 引数を
1
にすると異常終了。
- 引数を
*os.Fileはio.Readerとio.Writerを実装している
-
defer
で関数の遅延実行。- forの中で
defer
は避ける。
- forの中で
-
filepath.Walk
でディレクトリを再起的に処理できる。
インターフェース
-
interface{}
:Java の Object 型のように扱える。 - 関数とインターフェース:https://go.dev/play/p/Rcf_kLsDXe
- スライスとインターフェース:https://go.dev/play/p/6nVpm9oEj9
- スライスは他の型と互換性がないため代入出来ない。
- 型アサーション:https://go.dev/play/p/damAyk6QHa
- インタフェース型の値を任意の型にキャストする。
- Go 言語には型階層(型の親子関係?)は作れない。
- 構造体の匿名フィールドを埋め込める。(継承ではない)
- リンクの21行目でアンパサンド(
&
)で、どの変数(おそらくFuga
?)のポインタを参照しているのか、なぜポインタを参照する必要があるのかがわからない。 - 埋め込むと構造体の最上部と埋め込まれた型名で、フィールドとメソッドを参照できる。
- リンクの21行目でアンパサンド(
-
type
,interface
,struct
の棲み分けがいまいち掴めていない。
このスクラップは2024/01/21にクローズされました