Go

2026.04.10

公式ドキュメント

この記事の要点

goroutinechannelによる並行処理がGoの最大の強み
• エラー処理はif err != nilパターンが基本
go mod tidyで依存管理、go test -raceでレース検出

概要

Go(Golang)は Google が開発した静的型付けのコンパイル言語で、シンプルな文法・強力な標準ライブラリ・並行処理モデル(goroutine/channel)が特徴です。本チートシートは Go 1.22+ を前提に、実務で頻出する構文とツールチェーンの使い方を整理しています。

go ツールチェーン

コマンド説明
go versionバージョン確認
go mod init example.com/appモジュール初期化
go mod tidy依存関係を整理
go mod download依存をダウンロード
go get pkg@latest依存を追加/更新
go run .カレントパッケージを実行
go run main.goファイルを指定して実行
go build ./...ビルド
go build -o bin/app出力名指定
go install ./cmd/app$GOBIN にインストール
go test ./...全テスト実行
go test -run TestX -v個別実行+詳細出力
go test -race ./...レース検出
go test -coverカバレッジ
go vet ./...静的検査
gofmt -w .フォーマット
go fmt ./...パッケージ単位整形
go doc pkg.Funcドキュメント表示
go env環境変数表示
go work initマルチモジュール作業環境

ポイント: go mod tidyは使っていない依存を削除し、必要な依存を追加します。コミット前に必ず実行する習慣をつけましょう。

クロスコンパイル

コマンド説明
GOOS=linux GOARCH=amd64 go build -o bin/app-linuxLinux 用にビルド
GOOS=darwin GOARCH=arm64 go build -o bin/app-macmacOS (ARM) 用にビルド
GOOS=windows GOARCH=amd64 go build -o bin/app.exeWindows 用にビルド

基本型

説明
bool真偽値
int / int8..64整数
uint / uint8..64符号なし整数
float32 / float64浮動小数
complex64 / complex128複素数
string文字列(不変)
runeUnicode コードポイント(int32)
byteuint8 の別名
error組込エラーインターフェース

変数と定数

var x int = 1
var y = 2.5           // 型推論
z := "hello"          // 短い宣言(関数内のみ)
const Pi = 3.14
const (
    A = iota // 0
    B        // 1
    C        // 2
)

制御構文

if x > 0 {
    // ...
} else if x == 0 {
    // ...
} else {
    // ...
}

// if に初期化式
if v, err := f(); err != nil {
    return err
} else {
    use(v)
}

for i := 0; i < 10; i++ { /* ... */ }
for i, v := range slice { /* ... */ }
for k, v := range m { /* ... */ }
for ch := range channel { /* ... */ }
for { break } // 無限ループ

switch x {
case 1, 2:
    // ...
case 3:
    fallthrough
default:
    // ...
}

switch v := any.(type) { // 型スイッチ
case int: _ = v
case string: _ = v
}

関数

func add(a, b int) int { return a + b }

// 複数戻り値
func divmod(a, b int) (int, int) { return a / b, a % b }

// 名前付き戻り値
func parse(s string) (n int, err error) {
    n, err = strconv.Atoi(s)
    return
}

// 可変長引数
func sum(xs ...int) int {
    total := 0
    for _, v := range xs { total += v }
    return total
}

// 関数値・クロージャ
add := func(a, b int) int { return a + b }

実践メモ: :=(短い宣言)は関数内でのみ使用可能。パッケージレベルではvarを使います。

エラー処理

import "errors"
import "fmt"

var ErrNotFound = errors.New("not found")

func find(id int) (*User, error) {
    if id <= 0 {
        return nil, fmt.Errorf("find: invalid id %d: %w", id, ErrNotFound)
    }
    // ...
    return u, nil
}

// 呼び出し側
u, err := find(0)
if err != nil {
    if errors.Is(err, ErrNotFound) { /* ... */ }
    var pe *os.PathError
    if errors.As(err, &pe) { /* ... */ }
    return err
}

注意: エラーは必ず%wラップしましょう。fmt.Errorf("...: %w", err)にするとerrors.Is/Asでチェーンを辿れます。

構造体とメソッド

type User struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
}

func (u User) Greet() string       { return "hi " + u.Name }   // 値レシーバ
func (u *User) Rename(n string)    { u.Name = n }              // ポインタレシーバ

u := User{ID: 1, Name: "Ada"}
u.Rename("Grace")

インターフェース

type Stringer interface {
    String() string
}

type Animal struct{ Name string }
func (a Animal) String() string { return a.Name }

var s Stringer = Animal{"cat"}
fmt.Println(s)

// 型アサーション
a, ok := s.(Animal)

ジェネリクス(1.18+)

func Map[T, U any](xs []T, f func(T) U) []U {
    out := make([]U, len(xs))
    for i, v := range xs { out[i] = f(v) }
    return out
}

type Number interface { ~int | ~float64 }

func Sum[T Number](xs []T) T {
    var s T
    for _, v := range xs { s += v }
    return s
}

スライス・マップ

// スライス
s := []int{1, 2, 3}
s = append(s, 4, 5)
sub := s[1:3]
s2 := make([]int, 0, 10) // len 0, cap 10
c := make([]int, len(s))
copy(c, s)

// マップ
m := map[string]int{"a": 1}
m["b"] = 2
v, ok := m["a"]
delete(m, "a")
for k, v := range m { _ = k; _ = v }

ポイント: Goのインターフェース暗黙的に満たされます(implements宣言不要)。メソッドさえ一致すれば型は自動的にインターフェースを実装します。

並行処理(goroutine / channel)

// goroutine
go func() { fmt.Println("hello") }()

// チャネル
ch := make(chan int)        // アンバッファ
buf := make(chan int, 10)   // バッファ付き
ch <- 1                     // 送信
v := <-ch                   // 受信
close(ch)                   // クローズ
for v := range ch { _ = v }

// select
select {
case v := <-ch1:
    _ = v
case ch2 <- 42:
case <-time.After(1 * time.Second):
    // タイムアウト
default:
    // どれも準備できていない
}

注意: goroutineのリークに注意。送信先のないチャネルや、終了しないgoroutineはメモリリークの原因になります。必ずclosecontextで制御しましょう。

sync パッケージ

var mu sync.Mutex
mu.Lock(); defer mu.Unlock()

var wg sync.WaitGroup
for i := 0; i < 5; i++ {
    wg.Add(1)
    go func(i int) {
        defer wg.Done()
        work(i)
    }(i)
}
wg.Wait()

var once sync.Once
once.Do(func() { /* 初期化 */ })

context

ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()

req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
resp, err := http.DefaultClient.Do(req)

実践メモ: deferは関数の終了時に必ず実行されます。ファイルのClose、Mutexの Unlock、レスポンスBodyのCloseに活用しましょう。

実用スニペット集

1. HTTP サーバ

package main

import (
    "log"
    "net/http"
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("ok"))
    })
    log.Fatal(http.ListenAndServe(":8080", mux))
}

2. HTTP クライアント

resp, err := http.Get("https://example.com")
if err != nil { return err }
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)

3. JSON のエンコード/デコード

b, _ := json.Marshal(user)
var u User
_ = json.Unmarshal(b, &u)

4. ファイル読み書き

data, err := os.ReadFile("in.txt")
_ = os.WriteFile("out.txt", data, 0o644)

5. 行単位で読む

f, _ := os.Open("log.txt")
defer f.Close()
sc := bufio.NewScanner(f)
for sc.Scan() { fmt.Println(sc.Text()) }

6. コマンドライン引数

flag.StringVar(&name, "name", "world", "greet target")
flag.Parse()

7. 環境変数

port := os.Getenv("PORT")
if port == "" { port = "8080" }

8. 文字列操作

strings.Contains(s, "go")
strings.Split(s, ",")
strings.Join(parts, "-")
strings.ReplaceAll(s, "a", "b")
strings.ToLower(s)

9. 数値変換

n, err := strconv.Atoi("42")
s := strconv.Itoa(42)
f, _ := strconv.ParseFloat("3.14", 64)

10. 並行処理でエラー集約

import "golang.org/x/sync/errgroup"

g, ctx := errgroup.WithContext(ctx)
for _, url := range urls {
    url := url
    g.Go(func() error { return fetch(ctx, url) })
}
if err := g.Wait(); err != nil { return err }

11. テスト

func TestAdd(t *testing.T) {
    got := Add(1, 2)
    if got != 3 { t.Errorf("got %d", got) }
}

func TestTable(t *testing.T) {
    cases := []struct{ a, b, want int }{
        {1, 2, 3},
        {0, 0, 0},
    }
    for _, c := range cases {
        t.Run(fmt.Sprintf("%d+%d", c.a, c.b), func(t *testing.T) {
            if got := Add(c.a, c.b); got != c.want {
                t.Errorf("got %d want %d", got, c.want)
            }
        })
    }
}

12. ベンチマーク

func BenchmarkAdd(b *testing.B) {
    for i := 0; i < b.N; i++ { Add(1, 2) }
}

13. embed で静的ファイルを埋め込む

import _ "embed"

//go:embed static/*
var static embed.FS

14. slog 構造化ログ

logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
logger.Info("started", "port", 8080)

15. 依存注入(シンプル)

type Repo interface { Find(id int) (*User, error) }

type Service struct{ repo Repo }

func NewService(r Repo) *Service { return &Service{repo: r} }

よく使う標準ライブラリ

パッケージ用途
fmt書式付き入出力
osOS 操作・環境変数
io / io/fsI/O 抽象化
bufioバッファ付き I/O
strings / strconv文字列・数値変換
bytes[]byte 操作
encoding/jsonJSON
net/httpHTTP サーバ/クライアント
contextキャンセル・期限
time時刻
sync / sync/atomic並行制御
errorsエラーラッピング
log/slog構造化ログ
testingテスト
database/sqlSQL DB

トラブルシューティング

状況原因 / 対処
go: cannot find main modulego mod init を実行
undefined: Ximport 漏れ。goimports を使うと自動追加
assignment mismatch戻り値の個数と受け取り数が不一致
concurrent map writessync.Mutexsync.Map を使う
nil pointer dereferenceポインタ初期化を確認
fatal error: all goroutines are asleep - deadlock!受信のないチャネル送信等。close やバッファを検討
go test が遅い-run で対象を絞る、t.Parallel() を検討

Tips

  • フォーマットは必ず gofmt(もしくは goimports)。CI で検査する。
  • go vetstaticcheck を CI に入れると品質が上がる。
  • エラーは fmt.Errorf("...: %w", err) でラップし、errors.Is/As で判定する。
  • defer は関数末尾で確実に実行されるので、クローズ・ロック解放に使う。
  • 大きな struct は値渡しでなくポインタ渡しを検討(ただしレシーバ型は統一)。
  • context.Context は関数の第 1 引数に置くのが慣習。
  • ゴルーチンリークに注意: 送信側が終了しないチャネルは必ず close する。

参考リソース

この技術を体系的に学びたいですか?

未来学では東証プライム上場企業のITエンジニアが24時間サポート。月額24,800円から、退会金0円のオンラインIT塾です。

メールで無料相談する
← 一覧に戻る