本文へスキップ
Typle
ログイン状態を確認中

プログラミング · Go

Go構文のタイピング練習

Go の構文を、初級・中級・上級の3つのリストで打って覚えます。package と import、:= による宣言、if・for・switch、関数と複数の戻り値、構造体とメソッド、エラー処理まで、実際に書く形のまま練習できます。

3リスト・109語

無料・ログインなしで練習できます。押すとこのパックをフォローし、すぐに練習が始まります。

収録している言葉

Go構文(初級)

打つ言葉意味・補足
package mainpackage:所属パッケージを宣言(mainパッケージのmain関数が実行開始点)
import "fmt"import:パッケージを読み込む(未使用importはコンパイルエラー)
// コメント//:1行コメント
var age intvar 名前 型:ゼロ値で宣言(intのゼロ値は0)
var age int = 20var 名前 型 = 値:型と初期値を指定
var age = 20var 名前 = 値:型推論で宣言
age := 20名前 := 値:短い変数宣言(関数内のみ。同じブロックでは左辺に少なくとも1つ新しい変数が必要)
age = 21名前 = 値:既存変数への代入(ageは宣言済みであること)
const Max = 100const:定数
_ = age_:値を捨てる(ブランク識別子)
var enabled boolbool:真偽値(ゼロ値false)
name := "Pomo"string:文字列(ゼロ値は空文字。文字列は不変)
var b byte = 'A'byte:uint8の別名
var r rune = 'あ'rune:int32の別名(Unicodeコードポイントなどに使用)
same := a == b== / !=:等値・不等値比較(比較できない型もある)
count += 2+= -= *= /=:複合代入
count++++ / --:1増減(式ではなく文。x := count++は不可)
n := 1 << 3<< / >>:ビットシフト
for { break }for:無限ループ
if done { break }break:ループを抜ける(break可能な構文内で使用)
return resultreturn:関数から戻る
first := s[0]s[i]:要素へアクセス(範囲外はpanic)
part := s[1:3]s[low:high]:部分範囲(low以上high未満。元の配列を共有する場合がある)
n := len(s)len:長さ(文字列ではバイト数)
name := u.Name値.フィールド:フィールド参照
p := &u&値:アドレス取得
var p *User*型:ポインタ型(ゼロ値はnil)
copyOfUser := *p*ポインタ:参照先の値(nilの参照外しはpanic)
u.Birthday()値.メソッド():メソッド呼び出し(必要な条件下でアドレス取得等が自動的に補われる)
defer f.Close()defer:関数終了時の処理を登録(ファイルを正常に開いた後に登録。後入れ先出し。引数は登録時に評価)
go work()go f():goroutineで実行(mainの終了時に他のgoroutineを自動で待たない)
ch <- 10ch <- value:channelへ送信(閉じたchannelへの送信はpanic)
value := <-chchannelから受信
close(ch)channelを閉じる(通常は送信側が所有権を持って閉じる。二重closeはpanic)
_ = value未使用ローカル変数・import:コンパイル時の検査(未使用のローカル変数やimportは通常エラー)
var p *User = nilnil:参照を持たない値(ポインタ・スライス・map・channel・関数・インターフェース等で使用)
gofmt -w main.gogofmt:標準書式で整形(Go構文ではなくターミナルのコマンド。ファイルを上書き)

Go構文(中級)

打つ言葉意味・補足
import ( "fmt"; "errors" )import (...):複数パッケージを読み込む
/* 複数行の コメント *//* ... */:複数行コメント
if true { fmt.Println("OK") }{ ... }:ブロック(通常は行末のセミコロンを省略。開始の{はifやfuncなどと同じ行)
name, age := "Pomo", 20複数の短い変数宣言:複数変数を宣言
f := float64(age)型(値):明示的な型変換(数値型間でも通常は暗黙に変換しない)
s := strconv.Itoa(age)strconv.Itoa:整数の文字列表現を得る(strconvのimportが必要。string(age)は整数の10進文字列化ではない)
var count int64 = 100int / int64:符号付き整数(ゼロ値0。intの幅は実装に依存)
var count uint64 = 100uint / uint64:符号なし整数(ゼロ値0)
var rate float64 = 0.5float32 / float64:浮動小数点数(ゼロ値0)
remainder := 10 % 3+ - * / %:加減乗除・余り(%は整数。整数同士の除算は小数部を切り捨て)
adult := age >= 20< <= > >=:大小比較(順序比較可能な型で使用)
ok := enabled && !blocked&& || !:論理演算
masked := flags & 3& | ^ &^:ビット演算(整数型で使用。&は文脈によってアドレス取得)
for count < 5 { count++ }for 条件:条件ループ
if skip { continue }continue:次の繰り返しへ(ループ内で使用)
total := sum(values...)引数...:スライスを可変長引数へ展開(valuesは[]int)
a := [3]int{ 1, 2, 3 }[長さ]型{...}:固定長配列(長さは型の一部)
s := []int{ 1, 2, 3 }[]型{...}:スライス
s := make([]int, 3)make([]型, 長さ):指定長のスライス(要素はゼロ値)
s := make([]int, 0, 10)make([]型, 長さ, 容量):長さ・容量を指定
s = append(s, 4)append:スライスに追加(返り値を受け取る)
capacity := cap(s)cap:スライスの容量
m := make(map[string]int)make(map[キー型]値型):空のmapを作成
m["apple"] = 120m[key] = value:追加・更新(nilのmapへの書き込みはpanic)
v, ok := m["apple"]v, ok := m[key]:値と存在有無を取得(存在しない場合vは値型のゼロ値)
delete(m, "apple")delete:キーを削除(存在しないキーでもエラーにならない)
var v any = "hello"any:任意の型を保持(interface{}の別名)
s := v.(string)v.(型):型アサーション(型が異なるとpanic)
s, ok := v.(string)v, ok := x.(型):安全な型アサーション(型が異なる場合ok=false)
panic("想定外の状態")panic:スタックを巻き戻して通常処理を中断(通常の失敗はerrorで扱う)
n, ok := First([]int{ 10, 20 })型引数の推論:型引数を省略(推論できる場合のみ)
ch := make(chan int)make(chan 型):バッファなしchannel(送受信に相手が必要)
ch := make(chan int, 10)make(chan 型, 容量):バッファ付きchannel(満杯の送信・空の受信は待つ)
value, ok := <-ch受信値と状態(閉じてバッファが空ならok=false)
func Exported() { }大文字開始の名前:パッケージ外へ公開(外側の型・パッケージ等のアクセス条件も関係)
n := len("あ")len(文字列):文字列のバイト数(UTF-8で3。Unicodeコードポイント数ならutf8.RuneCountInString等)

Go構文(上級)

打つ言葉意味・補足
func main() { fmt.Println("Hello, Go!") }func main():実行開始の関数(fmtのimportが必要)
var label string; if age >= 20 { label = "成人" } else { label = "未成年" }三項演算子なし:条件による値の選択(条件 ? A : Bは使わない)
if age >= 20 { fmt.Println("成人") } else { fmt.Println("未成年") }if / else:条件で分岐(条件を丸括弧で囲む必要はない。elseは直前の}と同じ行)
if n := len(name); n > 0 { fmt.Println(n) }if 初期化; 条件:初期化付きの条件分岐(nはこのifと続くelse内で有効)
switch role { case "admin": fmt.Println("管理者"); case "member", "guest": fmt.Println("一般利用者"); default: fmt.Println("不明") }switch / case / default:値で分岐(通常はcase末尾にbreak不要)
for i := 0; i < 5; i++ { fmt.Println(i) }for 初期化; 条件; 更新:回数指定ループ(while構文はない)
for i, v := range items { fmt.Println(i, v) }for i, v := range items:添字と値を取得(itemsは配列・スライス等)
for _, v := range items { fmt.Println(v) }for _, v := range items:値だけを使用
for k, v := range m { fmt.Println(k, v) }for k, v := range m:mapのキーと値を取得(mapの列挙順は保証されない)
for i, r := range "あいう" { fmt.Println(i, r) }文字列のrange:バイト位置とruneを取得(添字は文字番号ではなくバイト位置)
func greet(name string) { fmt.Println(name) }func 名前(引数):戻り値なしの関数
func add(a, b int) int { return a + b }func 名前(引数) 型:戻り値ありの関数
func pair() (int, string) { return 1, "one" }複数の戻り値:複数の値を返す
func sum(nums ...int) int { total := 0; for _, n := range nums { total += n }; return total }...型:可変長引数(可変長引数は最後に置く)
f := func(x int) int { return x * 2 }無名関数:関数を値として保持
func() { fmt.Println("実行") }()func() { ... }():無名関数を即時実行
m := map[string]int{ "apple": 100 }map[キー型]値型{...}:mapを作成(キー型はcomparable)
type User struct { Name string; Age int }type 名前 struct:構造体を定義
u := User{ Name: "Pomo", Age: 20 }型{フィールド: 値}:構造体の値を作る
func (u User) Greet() string { return "こんにちは、" + u.Name }値レシーバー:値を受け取るメソッド
func (u *User) Birthday() { u.Age++ }ポインタレシーバー:参照先を変更するメソッド
type Greeter interface { Greet() string }type 名前 interface:メソッドの集合を定義(必要なメソッドを持つ型が暗黙に満たす)
var g Greeter = User{ Name: "Pomo" }インターフェースへ代入:実装を抽象型で扱う(UserにGreetメソッドが必要)
switch x := v.(type) { case string: fmt.Println(x); case int: fmt.Println(x) }switch x := v.(type):型による分岐
func divide(a, b int) (int, error) { if b == 0 { return 0, errors.New("ゼロでは割れません") }; return a / b, nil }errorの戻り値:通常の失敗を値で返す(errorsのimportが必要)
result, err := divide(10, 2); if err != nil { fmt.Println(err); return }; fmt.Println(result)if err != nil:エラーを確認(例はmain関数内)
err := errors.New("失敗しました")errors.New:エラーを生成(errorsのimportが必要)
return fmt.Errorf("読み込み失敗: %w", err)fmt.Errorf / %w:元のエラーをラップ(errorを返す関数内。fmtのimportが必要)
defer func() { if r := recover(); r != nil { fmt.Println(r) } }()recover:同じgoroutineのpanicを回収(deferされた関数内で直接呼ぶ)
func First[T any](items []T) (T, bool) { if len(items) == 0 { var zero T; return zero, false }; return items[0], true }[T any]:任意の型の型パラメーター
func Equal[T comparable](a, b T) bool { return a == b }[T comparable]:比較可能な型に制限
n, ok := First[int]([]int{ 10, 20 })関数[型](引数):型引数を明示
for v := range ch { fmt.Println(v) }for v := range ch:終了まで受信(閉じられて値が尽きると終了)
select { case v: = <-ch: fmt.Println(v); case <-done: return }select:複数の通信を待つ(この例は関数内。chとdoneは初期化済み)
ch := make(chan string); go func() { ch <- "完了" }(); message := <-ch; fmt.Println(message)goroutineとchannelの組合せ:送信・受信を同期(fmtのimportが必要)
package main; import "fmt"; func main() { fmt.Println("Hello, Go!") }コード例の前提:コード断片の利用範囲(多くの例は関数内の断片。宣言・import・変数等を補って利用)

ほかの公式パックを見る