4.

Go(.go)完全ガイド — Google 製・goroutine・単一バイナリ・go.mod

編集
この記事の要点
  • Go(Golang)は Google が 2009 年に発表した静的型付けコンパイル言語。シンプルさと並行処理を重視
  • ソースファイル拡張子は .gogo build で OS ごとの単一バイナリにコンパイルされ、ランタイム同梱で配布が容易
  • 並行処理は軽量スレッド「goroutine」と通信プリミティブ「channel」で実現。go func() {}() で起動
  • 依存管理は Go Modules(go.mod / go.sum)。1.11 以降が標準で、GOPATH 時代より遥かに扱いやすい
  • ガベージコレクション搭載でメモリ管理は自動。1.18 でジェネリクスが導入され、型パラメータ [T any] が書ける
  • gofmt が公式フォーマッタとして同梱され、コードスタイルの議論が起きにくい。go test / go vet も標準装備
  • CLI ツール・サーバーサイド・コンテナ周辺(Docker / Kubernetes / Terraform はすべて Go 製)に強い

概要

Go(通称 Golang)は、Google の Robert Griesemer・Rob Pike・Ken Thompson らが 2007 年に設計を開始し、2009 年 11 月にオープンソースとして公開された静的型付けコンパイル言語です。「C 言語ほど煩雑でなく、Python ほど遅くなく、Java ほど冗長でない」という現実的なバランスを狙って設計されました。ソースコードの拡張子は .go、コンパイル後はターゲット OS / アーキテクチャに応じた 単一の実行バイナリ が生成されます。

Go の最大の特徴は 並行処理(concurrency)モデル の優秀さです。go キーワードを関数呼び出しの前に置くだけで「goroutine」と呼ばれる軽量スレッドが起動し、channel によってスレッド間で安全に値を受け渡せます。これは Tony Hoare の CSP(Communicating Sequential Processes)理論を実装に落とし込んだものです。さらに ガベージコレクション(GC)を搭載しているため、C / C++ のような手動メモリ管理は不要です。

1.18(2022 年)でジェネリクスが導入され、func Map[T, U any](s []T, f func(T) U) []U のような型パラメータが書けるようになりました。1.21 で min / max / clear の組み込み、1.22 でループ変数のスコープ修正など、後方互換性を慎重に保ちつつ進化を続けています。

用途は CLI ツール・Web API サーバー・マイクロサービス・クラウドネイティブインフラ が中心。Docker・Kubernetes・Terraform・Prometheus・etcd・CockroachDB など、現代のインフラを支えるツールの多くが Go で書かれています。コンパイル速度が極めて速く、CI / CD と相性が良い点も普及の理由です。

ファイル種類とビルド成果物

拡張子 / ファイル役割ビルド経路
.goGo ソースコード入力
go.modモジュール定義(モジュール名・Go バージョン・依存)プロジェクトルート
go.sum依存のチェックサム(ハッシュ検証)自動生成
実行バイナリ(拡張子なし / .exeOS ネイティブ単一バイナリgo build の出力
_test.goテストコード(同パッケージ内)go test が拾う

Go は 中間ファイル(.class / .pyc 等)をユーザーに意識させない 設計です。$GOCACHE に隠れてはいますが、開発者が直接触ることはまずありません。配布物は単一バイナリで完結し、ランタイムや libc を別途配る必要がない(CGO を使わない限り)のが大きな利点です。

「Hello, World」

package main

import "fmt"

func main() {
    fmt.Println("Hello, World")
}

ビルドと実行:

$ go mod init example.com/hello
$ go build -o hello
$ ./hello
Hello, World

# クロスコンパイル(Linux 上で Windows 用バイナリを作る)
$ GOOS=windows GOARCH=amd64 go build -o hello.exe

パッケージ管理・ビルドツール

Go の依存管理は Go Modules(1.11 から導入、1.16 で正式デフォルト)が標準です。go.mod にモジュールパス・Go バージョン・依存を書き、go.sum でハッシュを固定します。

go mod init example.com/myapp     # 初期化
go get github.com/gin-gonic/gin   # 依存追加
go build ./...                    # 全パッケージビルド
go test ./...                     # 全テスト実行
go vet ./...                      # 静的解析
gofmt -w .                        # コード整形
go run main.go                    # コンパイル + 実行(中間バイナリは破棄)

関連言語との比較

項目GoRustJavaPython
型システム静的・GC あり静的・GC なし(所有権)静的・GC あり動的
配布単一バイナリ単一バイナリJAR + JVM 必要ソース + ランタイム
並行処理goroutine + channelasync / await + Send/SyncThread / Virtual Threadasyncio / GIL 制約
学習コスト低(言語仕様が小さい)高(所有権が壁)
コンパイル速度非常に速い遅い速い—(インタプリタ)

注意点・落とし穴

  • エラー処理が冗長if err != nil { return err } が頻出。例外がないので、エラーは値として明示的に伝播させる必要がある。
  • ループ変数のスコープ:1.22 未満では for _, v := range items { go func() { use(v) }() }v が共有され、典型的バグになる。1.22 以降はループ毎に新しい変数が作られるので解消。
  • nil interface ハマり:型情報を持つ nil(typed nil)と純粋な nil は == 比較で挙動が違う。
  • 循環インポート禁止:パッケージ A → B → A は許可されない。設計段階でレイヤを切る必要がある。
  • ジェネリクスは後付け:標準ライブラリの多くが interface{} ベースで設計されているため、新旧 API が混在しがち。

関連リンク

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. Python(.py / .pyc)
  2. JavaScript(.js / .mjs / .cjs)
  3. TypeScript(.ts / .tsx)
  4. Go(.go)
  5. Rust(.rs)
  6. Java(.java / .class / .jar)
  7. C / C++(.c / .h / .cpp / .hpp)
  8. Ruby(.rb)
  9. Swift(.swift)
  10. Kotlin(.kt / .kts)

最近更新/作成されたページ