基本
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
基本型
booltruefalse
stringUTF-8 の不変バイト列
int, int8..int64符号付き整数(プラットフォーム / 固定幅)
uint, uint8..uint64符号なし整数
float32, float64IEEE-754 浮動小数点
byteuint8 の別名
runeint32 の別名(Unicode コードポイント)
ゼロ値
int, float0
boolfalse
string"" (空文字列)
pointer, slice, mapnil
関数
基本関数
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: "[email protected]", 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 }
よく使うインターフェース
io.ReaderRead(p []byte) (n int, err error)
io.WriterWrite(p []byte) (n int, err error)
fmt.StringerString() string
errorError() 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") }
パターン
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 パッケージ
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 { }
スライス操作
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 などのキーワードは不要。
よく使う標準ライブラリ
fmtフォーマット I/O(Print、Sprintf、Errorf)
osOS 関数(ファイル、環境変数、引数)
ioI/O プリミティブ(Reader、Writer)
net/httpHTTP クライアントとサーバー
encoding/jsonJSON エンコード/デコード
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) } }
テストコマンド
go testカレントパッケージのテストを実行
go test ./...すべてのテストを再帰的に実行
go test -v詳細な出力
go test -run TestAdd名前で特定のテストを実行
go test -bench .ベンチマークを実行
go test -coverカバレッジのパーセンテージを表示