# Go クイックリファレンス

*構文、型、並行処理、エラーハンドリングの基礎*

> Source: The Go Programming Language (go.dev) · MIT

## 基本

### Hello World

```
package main
import "fmt"
func main() {
    fmt.Println("Hello, World!")
}
```

### 実行とビルド

```
go run main.go        # コンパイルして実行
go build -o app .     # バイナリにコンパイル
go test ./...         # すべてのテストを実行
```

### モジュールの初期化

```
go mod init github.com/user/project
go mod tidy           # 依存関係を同期
```

## 変数と型

### 宣言

```
var name string = "Go"
age := 15               // 短縮宣言
var x, y int = 1, 2
const Pi = 3.14159
```

### 基本型

| Command | Description |
|---------|-------------|
| `bool` | `true`、`false` |
| `string` | UTF-8 の不変バイト列 |
| `int, int8..int64` | 符号付き整数（プラットフォーム / 固定幅） |
| `uint, uint8..uint64` | 符号なし整数 |
| `float32, float64` | IEEE-754 浮動小数点 |
| `byte` | `uint8` の別名 |
| `rune` | `int32` の別名（Unicode コードポイント） |

### ゼロ値

| Command | Description |
|---------|-------------|
| `int, float` | `0` |
| `bool` | `false` |
| `string` | `""` （空文字列） |
| `pointer, slice, map` | `nil` |

## 関数

### 基本関数

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

### 複数の戻り値

```
func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
}
```

### 可変長引数と無名関数

```
func sum(nums ...int) int {
    total := 0
    for _, n := range nums { total += n }
    return total
}
double := func(x int) int { return x * 2 }
```

### defer

```
func readFile(path string) {
    f, _ := os.Open(path)
    defer f.Close()   // 関数が返るときに実行
}
```

## 制御フロー

### if / else

```
if x > 0 {
    fmt.Println("positive")
} else if x == 0 {
    fmt.Println("zero")
} else {
    fmt.Println("negative")
}
```

### for ループ

```
for i := 0; i < 10; i++ { }  // 従来型
for x < 100 { x *= 2 }       // while スタイル
for { break }                 // 無限ループ
for i, v := range slice { }   // range
```

### switch

```
switch day {
case "Mon", "Tue":
    fmt.Println("early week")
case "Fri":
    fmt.Println("TGIF")
default:
    fmt.Println("other")
}
```

## 構造体とメソッド

### 構造体の定義

```
type User struct {
    Name  string
    Email string
    Age   int
}
u := User{Name: "Alice", Email: "a@b.com", Age: 30}
```

### メソッド

```
func (u User) Greeting() string {
    return "Hi, " + u.Name
}
func (u *User) SetAge(age int) {
    u.Age = age   // ポインタレシーバーで変更
}
```

### 埋め込み

```
type Admin struct {
    User          // 埋め込み構造体
    Level string
}
a := Admin{User: User{Name: "Bob"}, Level: "super"}
fmt.Println(a.Name)  // 昇格フィールド
```

## インターフェース

### 定義と実装

```
type Stringer interface {
    String() string
}
// 暗黙の実装 — "implements" キーワードなし
func (u User) String() string {
    return u.Name
}
```

### よく使うインターフェース

| Command | Description |
|---------|-------------|
| `io.Reader` | `Read(p []byte) (n int, err error)` |
| `io.Writer` | `Write(p []byte) (n int, err error)` |
| `fmt.Stringer` | `String() string` |
| `error` | `Error() string` |

### 型アサーション

```
var i interface{} = "hello"
s, ok := i.(string)   // ok == true
switch v := i.(type) {
case string: fmt.Println(v)
case int:    fmt.Println(v * 2)
}
```

## ゴルーチンとチャンネル

### ゴルーチン

```
go func() {
    fmt.Println("running concurrently")
}()
time.Sleep(time.Second)
```

### チャンネル

```
ch := make(chan int)       // バッファなし
buf := make(chan int, 5)   // バッファ付き
ch <- 42                   // 送信
val := <-ch                // 受信
```

### select

```
select {
case msg := <-ch1:
    fmt.Println(msg)
case ch2 <- 42:
    fmt.Println("sent")
case <-time.After(time.Second):
    fmt.Println("timeout")
}
```

### パターン

| Command | Description |
|---------|-------------|
| `sync.WaitGroup` | 複数のゴルーチンの完了を待つ |
| `sync.Mutex` | 共有状態のための相互排除ロック |
| `context.Context` | キャンセル、デッドライン、リクエストスコープの値 |

## エラーハンドリング

### 基本パターン

```
result, err := doSomething()
if err != nil {
    return fmt.Errorf("failed: %w", err)
}
```

### カスタムエラー

```
type NotFoundError struct {
    ID string
}
func (e *NotFoundError) Error() string {
    return "not found: " + e.ID
}
```

### errors パッケージ

| Command | Description |
|---------|-------------|
| `errors.New(msg)` | シンプルなエラーを作成 |
| `fmt.Errorf("%w", err)` | コンテキスト付きでエラーをラップ |
| `errors.Is(err, target)` | エラーチェーンで一致を確認 |
| `errors.As(err, &target)` | チェーンから型付きエラーを取り出す |

## スライスとマップ

### スライス

```
s := []int{1, 2, 3}
s = append(s, 4, 5)
sub := s[1:3]             // [2, 3]
cp := make([]int, len(s))
copy(cp, s)
```

### マップ

```
m := map[string]int{"a": 1, "b": 2}
m["c"] = 3
val, ok := m["a"]        // ok == true
delete(m, "b")
for k, v := range m { }
```

### スライス操作

| Command | Description |
|---------|-------------|
| `len(s)` | 要素数 |
| `cap(s)` | 内部配列の容量 |
| `append(s, elems...)` | 要素を追加（再割り当てが発生する場合あり） |
| `copy(dst, src)` | スライス間で要素をコピー |
| `slices.Sort(s)` | スライスをソート（Go 1.21+ の `slices` パッケージ） |

## パッケージとインポート

### インポートスタイル

```
import "fmt"
import (
    "os"
    "strings"
    "github.com/user/pkg"
)
```

### 可視性

> 先頭が大文字 = エクスポート済み（公開）。
先頭が小文字 = エクスポートなし（パッケージプライベート）。
public/private などのキーワードは不要。

### よく使う標準ライブラリ

| Command | Description |
|---------|-------------|
| `fmt` | フォーマット I/O（Print、Sprintf、Errorf） |
| `os` | OS 関数（ファイル、環境変数、引数） |
| `io` | I/O プリミティブ（Reader、Writer） |
| `net/http` | HTTP クライアントとサーバー |
| `encoding/json` | JSON エンコード/デコード |
| `strings` | 文字列操作関数 |
| `strconv` | 文字列と数値の変換 |
| `testing` | ユニットテストフレームワーク |

## ジェネリクス

### 型パラメーター

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

### 制約

```
type Number interface {
    ~int | ~float64
}
func Sum[T Number](nums []T) T {
    var total T
    for _, n := range nums { total += n }
    return total
}
```

## テスト

### 基本テスト

```
// ファイル: math_test.go
func TestAdd(t *testing.T) {
    got := Add(2, 3)
    if got != 5 {
        t.Errorf("Add(2,3) = %d, want 5", got)
    }
}
```

### テストコマンド

| Command | Description |
|---------|-------------|
| `go test` | カレントパッケージのテストを実行 |
| `go test ./...` | すべてのテストを再帰的に実行 |
| `go test -v` | 詳細な出力 |
| `go test -run TestAdd` | 名前で特定のテストを実行 |
| `go test -bench .` | ベンチマークを実行 |
| `go test -cover` | カバレッジのパーセンテージを表示 |
