Go
エンジニアのためのWebチートシート
Go(Golang)は、Googleが開発した静的型付けのコンパイル言語です。 シンプルな構文、高速なコンパイル、組み込みの並行処理(goroutine)が特徴です。 基本構文、データ型、関数、構造体、エラー処理、並行処理などをチートシートにまとめました。
基本構文
変数宣言
var, :=, const による変数・定数の宣言です。
var name string = "Go" var age int = 15 var isActive bool // 短縮宣言(関数内のみ) name := "Go" age := 15 // 複数宣言 var ( host string = "localhost" port int = 8080 )const Pi = 3.14159 const ( StatusOK = 200 StatusNotFound = 404 )
出力 & フォーマット
fmt パッケージによる出力とフォーマット指定子です。
import "fmt" fmt.Println("Hello, World!") // 改行付き出力 fmt.Print("Hello ") // 改行なし出力 // フォーマット出力 fmt.Printf("Name: %s\n", name) fmt.Printf("Age: %d\n", age) fmt.Printf("Pi: %.2f\n", 3.14159) fmt.Printf("Bool: %t\n", true) fmt.Printf("Type: %T\n", 42) // int fmt.Printf("Value: %v\n", obj) // デフォルト形式 fmt.Printf("Pointer: %p\n", &x) // 文字列に格納 s := fmt.Sprintf("Hello, %s!", name)
iota & 型変換
iota による連番定数と明示的な型変換です。
type Weekday int const ( Sunday Weekday = iota // 0 Monday // 1 Tuesday // 2 Wednesday // 3 ) const ( Read = 1 << iota // 1 (ビットフラグ) Write // 2 Execute // 4 )// 型変換(明示的キャストが必要) i := 42 f := float64(i) s := strconv.Itoa(i) // int → string n, _ := strconv.Atoi("42") // string → int
データ型
Goの基本データ型の一覧です。
| 型 | 説明 |
|---|---|
bool | true / false |
string | UTF-8 文字列(イミュータブル) |
int, int8, int16, int32, int64 | 符号付き整数 |
uint, uint8, uint16, uint32, uint64 | 符号なし整数 |
float32, float64 | 浮動小数点数 |
byte | uint8 のエイリアス |
rune | int32 のエイリアス(Unicodeコードポイント) |
complex64, complex128 | 複素数 |
文字列操作
文字列リテラルと strings パッケージの主要関数です。
s := "Hello, World!" s2 := `Raw string literal supports multiple lines` len(s) // 13(バイト数) len([]rune(s)) // 文字数 s[0:5] // "Hello"import "strings" strings.Contains(s, "World") // true strings.HasPrefix(s, "Hello") // true strings.ToUpper(s) // "HELLO, WORLD!" strings.TrimSpace(" hi ") // "hi" strings.Split("a,b,c", ",") // ["a","b","c"] strings.Join([]string{"a","b"}, ",") // "a,b" strings.Replace(s, "World", "Go", 1)
ポインタ
アドレス演算子とデリファレンスの基本です。
x := 42 p := &x // *int 型(xのアドレス) fmt.Println(*p) // 42(値を取得) *p = 100 // x も 100 に変更 p2 := new(int) // *int(ゼロ値 0) var p3 *int // nil// 関数でポインタを使う func increment(n *int) { *n++ } increment(&x) // x が 1 増加
制御フロー
if / else
条件分岐です。初期化付きifも使えます。
if x > 0 { fmt.Println("positive") } else if x == 0 { fmt.Println("zero") } else { fmt.Println("negative") }// 初期化付き if if err := doSomething(); err != nil { fmt.Println("error:", err) } if f, err := os.Open("file.txt"); err != nil { log.Fatal(err) } else { defer f.Close() }
for ループ
Goの唯一のループ構文です。while相当も for で書きます。
for i := 0; i < 10; i++ { fmt.Println(i) } n := 1 for n < 100 { // while 相当 n *= 2 } for { // 無限ループ(break で脱出) }// range で反復 for i, v := range []int{1, 2, 3} { fmt.Println(i, v) } for i, ch := range "Hello" { fmt.Printf("%d: %c\n", i, ch) } for k, v := range myMap { fmt.Println(k, v) }
switch
式switchと条件なしswitchです。自動breakで fallthrough は明示的です。
switch day { // 自動 break case "Mon", "Tue", "Wed", "Thu", "Fri": fmt.Println("Weekday") case "Sat", "Sun": fmt.Println("Weekend") default: fmt.Println("Unknown") }// 条件なし switch switch { case score >= 90: fmt.Println("A") case score >= 80: fmt.Println("B") default: fmt.Println("C") }// fallthrough(次のcaseも実行) switch n { case 1: fmt.Println("one") fallthrough case 2: fmt.Println("two or after one") }
関数
関数定義
複数戻り値と名前付き戻り値をサポートします。
func greet(name string) string { return "Hello, " + name } // 複数戻り値 func divide(a, b float64) (float64, error) { if b == 0 { return 0, errors.New("division by zero") } return a / b, nil }// 名前付き戻り値 func minMax(nums []int) (min, max int) { min, max = nums[0], nums[0] for _, n := range nums[1:] { if n < min { min = n } if n > max { max = n } } return }
可変長引数 & 無名関数
可変長引数、クロージャ、即時実行関数です。
func sum(nums ...int) int { total := 0 for _, n := range nums { total += n } return total } sum(1, 2, 3) // 6 sum([]int{1,2,3}...) // スライス展開// 無名関数(クロージャ) add := func(a, b int) int { return a + b } fmt.Println(add(1, 2)) // 3 // クロージャで状態を保持 func counter() func() int { n := 0 return func() int { n++ return n } }
defer
関数終了時に実行される遅延呼び出しです。LIFO順で実行されます。
func readFile() { f, err := os.Open("file.txt") if err != nil { log.Fatal(err) } defer f.Close() // 関数終了時に必ず閉じる }// LIFO 順で実行 defer fmt.Println("1st") defer fmt.Println("2nd") defer fmt.Println("3rd") // 出力: 3rd, 2nd, 1stresp, err := http.Get("https://example.com") if err != nil { log.Fatal(err) } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body)
データ構造
配列 & スライス
固定長の配列と可変長のスライスです。
var arr [3]int = [3]int{1, 2, 3} // 配列(固定長) arr2 := [...]int{1, 2, 3} // 長さ自動推論 s := []int{1, 2, 3} // スライス(可変長) s2 := make([]int, 5) // len=5, cap=5 s3 := make([]int, 0, 10) // len=0, cap=10s = append(s, 4, 5) // 追加 s = append(s, []int{6,7}...) // スライス追加 sub := s[1:3] // index 1〜2 head := s[:3] // 先頭3つ tail := s[2:] // index 2〜末尾 dst := make([]int, len(s)) copy(dst, s) len(s) // 長さ cap(s) // 容量
マップ
キーと値のペアを持つデータ構造です。
m := map[string]int{ "alice": 25, "bob": 30, } m2 := make(map[string]int) m["charlie"] = 35 // 追加・更新 age := m["alice"] // 取得(25) delete(m, "bob") // 削除// 存在確認(カンマOKイディオム) val, ok := m["dave"] if !ok { fmt.Println("not found") } for key, val := range m { fmt.Printf("%s: %d\n", key, val) } len(m) // 要素数
ゼロ値 & 型アサーション
未初期化変数のデフォルト値と型アサーションです。
// ゼロ値(未初期化のデフォルト値) // int, float → 0 bool → false string → "" // pointer, slice, map, chan, func, interface → nil type UserID int64 type Temperature float64// 型アサーション var i interface{} = "hello" s := i.(string) // "hello" s, ok := i.(string) // ok = true n, ok := i.(int) // ok = false// 型スイッチ switch v := i.(type) { case string: fmt.Println("string:", v) case int: fmt.Println("int:", v) default: fmt.Println("unknown") }
構造体 & インターフェース
構造体
構造体の定義、初期化、メソッドです。
type User struct { Name string Age int Email string } u1 := User{"Alice", 25, "alice@example.com"} u2 := User{Name: "Bob", Age: 30} u3 := &User{Name: "Charlie"} // ポインタ// 値レシーバ func (u User) Greet() string { return "Hi, I'm " + u.Name } // ポインタレシーバ(フィールド変更可能) func (u *User) SetAge(age int) { u.Age = age }
埋め込み & コンポジション
構造体の埋め込みによるコンポジションです。
type Animal struct { Name string } func (a Animal) Speak() string { return a.Name + " speaks" } type Dog struct { Animal // 埋め込み(コンポジション) Breed string }d := Dog{ Animal: Animal{Name: "Pochi"}, Breed: "Shiba", } fmt.Println(d.Name) // "Pochi"(昇格) fmt.Println(d.Speak()) // "Pochi speaks"
インターフェース
暗黙的に実装されるインターフェースです。
type Shape interface { Area() float64 Perimeter() float64 } // 暗黙的に実装(implements 不要) type Circle struct { Radius float64 } func (c Circle) Area() float64 { return math.Pi * c.Radius * c.Radius } func (c Circle) Perimeter() float64 { return 2 * math.Pi * c.Radius }func printAny(v any) { fmt.Println(v) } // Stringer インターフェース(fmt 出力用) func (u User) String() string { return fmt.Sprintf("%s (%d)", u.Name, u.Age) }
エラーハンドリング
基本
error 戻り値パターンとカスタムエラーです。
result, err := doSomething() if err != nil { log.Fatal(err) } func divide(a, b float64) (float64, error) { if b == 0 { return 0, errors.New("division by zero") } return a / b, nil }// カスタムエラー型 type ValidationError struct { Field string Message string } func (e *ValidationError) Error() string { return e.Field + ": " + e.Message }
errors パッケージ
エラーのラップ、比較、型アサーションです。
err := fmt.Errorf("open config: %w", os.ErrNotExist) if errors.Is(err, os.ErrNotExist) { fmt.Println("file not found") } var pathErr *os.PathError if errors.As(err, &pathErr) { fmt.Println("path:", pathErr.Path) }// errors.Join(Go 1.20+) err := errors.Join( errors.New("error 1"), errors.New("error 2"), ) var ErrNotFound = errors.New("not found") var ErrTimeout = errors.New("timeout")
panic & recover
パニックとリカバリーの基本です。
func mustEnv(key string) string { val := os.Getenv(key) if val == "" { panic("missing env: " + key) } return val }// recover: panic をキャッチする func safeDiv(a, b int) (result int, err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("recovered: %v", r) } }() return a / b, nil }
並行処理
goroutine
軽量スレッドで並行処理を実行します。
// goroutine: go キーワードで起動 go func() { fmt.Println("Hello from goroutine") }() // sync.WaitGroup で完了を待つ var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func(n int) { defer wg.Done() fmt.Println("Worker", n) }(i) } wg.Wait() // すべての goroutine が完了するまで待つ
チャネル
goroutine間でデータをやり取りする仕組みです。
ch := make(chan int) go func() { ch <- 42 }() val := <-ch // 受信(42) // バッファ付きチャネル ch := make(chan string, 3) ch <- "a" ch <- "b" ch <- "c"// close と range ch := make(chan int, 5) go func() { for i := 0; i < 5; i++ { ch <- i } close(ch) }() for v := range ch { fmt.Println(v) }
select & Mutex
複数チャネルの待ち受けと排他制御です。
select { case msg := <-ch1: fmt.Println("ch1:", msg) case msg := <-ch2: fmt.Println("ch2:", msg) case <-time.After(3 * time.Second): fmt.Println("timeout") }// sync.Mutex: 排他制御 type SafeCounter struct { mu sync.Mutex v map[string]int } func (c *SafeCounter) Inc(key string) { c.mu.Lock() defer c.mu.Unlock() c.v[key]++ }
パッケージ & ツール
パッケージ & インポート
パッケージの宣言とインポートの方法です。
package main // 実行可能プログラム package mylib // ライブラリ import ( "fmt" "os" "net/http" )import ( f "fmt" . "strings" // ドットインポート(非推奨) _ "image/png" // 副作用のみ ) // 大文字始まり → エクスポート func PublicFunc() {} func privateFunc() {} // パッケージ内のみ
Go コマンド
よく使うGoのCLIコマンドです。
go mod init myproject # モジュール初期化 go mod tidy # 依存関係の整理 go get github.com/pkg/errors # パッケージ追加 go run main.go # 実行 go build -o app . # ビルドgo test ./... # 全テスト実行 go test -v ./... # 詳細出力 go test -cover ./... # カバレッジ go test -bench=. ./... # ベンチマーク go fmt ./... # フォーマット go vet ./... # 静的解析