Goを実行してみよう
Goはコンパイルが速く、Web APIやコマンドラインツールなどに使われる言語です。公式ディストリビューションを導入し、go versionで確認します。
package main
import "fmt"
func main() {
fmt.Println("こんにちは、Go!")
}go run main.goこんにちは、Go!package mainとfunc main()が実行開始点です。保存後はgofmt -w main.goで自動整形できます。
変数とデータ型
varは型を明示し、:=は右辺から型を推論します。:=は関数内でのみ使えます。
name := "Mity" // string
var age int = 20 // int
height := 170.5 // float64
isStudent := true // bool
fmt.Printf("%sさん %d歳 %.1fcm %t\n", name, age, height, isStudent)Mityさん 20歳 170.5cm true入力と型変換
fmt.Scanはキーボード入力を変数へ読み込みます。戻り値のエラーも確認しましょう。
var age int
fmt.Print("年齢: ")
if _, err := fmt.Scan(&age); err != nil {
fmt.Println("整数で入力してください")
return
}
fmt.Printf("来年は%d歳です\n", age+1)年齢: 20
来年は21歳です演算子と条件分岐
比較は== != < > <= >=、論理演算は&& || !を使います。条件の括弧は不要です。
score := 82
if score >= 80 {
fmt.Println("合格(よくできました)")
} else if score >= 60 {
fmt.Println("合格")
} else {
fmt.Println("再挑戦")
}合格(よくできました)繰り返し
Goの繰り返しはfor一種類です。初期化、条件、更新をセミコロンで区切ります。
for i := 1; i <= 5; i++ {
fmt.Printf("%d回目\n", i)
}1回目
2回目
3回目
4回目
5回目for { }は条件がないため、breakなどで終了させない限り続きます。スライスとマップ
スライスは可変長の並び、マップはキーと値の組です。
fruits := []string{"りんご", "みかん"}
fruits = append(fruits, "ぶどう")
scores := map[string]int{"Aki": 82, "Mika": 91}
for i, fruit := range fruits {
fmt.Printf("%d: %s\n", i+1, fruit)
}
fmt.Printf("Mika: %d点\n", scores["Mika"])
if _, ok := scores["Ken"]; !ok {
fmt.Println("Ken: 未登録")
}1: りんご
2: みかん
3: ぶどう
Mika: 91点
Ken: 未登録マップからは値と存在を表すokを同時に受け取れます。上の例は値を使わないため_で破棄し、okがfalseのときに未登録と表示しています。値も必要ならvalue, ok := scores["Ken"]と書きます。
関数
関数は処理をまとめ、引数を受け取って結果を返します。
func total(price, count int) int {
return price * count
}
func main() {
fmt.Printf("合計: %d円\n", total(500, 3))
}合計: 1500円- 関数名は役割が伝わる名前にする
- 表示と計算を分ける
- 異常を返すときは値とerrorの2値を返す
エラーを値として扱う
Goでは想定可能な失敗をerrorで返し、呼び出し側ですぐ確認します。
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("0では割れません")
}
return a / b, nil
}
answer, err := divide(10, 0)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(answer)
}0では割れませんこの例ではerrorsパッケージのimportが必要です。panicは回復不能な状態に限り、通常の入力ミスには使いません。
ファイルの読み書き
os.WriteFileとos.ReadFileで小さなファイルを扱えます。処理ごとにエラーを確認します。
if err := os.WriteFile("memo.txt", []byte("Goを学習中\n"), 0644); err != nil {
log.Fatal(err)
}
data, err := os.ReadFile("memo.txt")
if err != nil {
log.Fatal(err)
}
fmt.Print(string(data))Goを学習中osとlogをimportします。利用者入力をそのままファイル名にせず、重要なファイルの上書きに注意してください。
構造体とメソッド
構造体は関連する値をまとめた型です。メソッドはレシーバーを持つ関数です。
type Product struct {
Name string
Price int
}
func (p Product) Label() string {
return fmt.Sprintf("%s: %d円", p.Name, p.Price)
}
product := Product{Name: "ノート", Price: 180}
fmt.Println(product.Label())ノート: 180円モジュールとテスト
プロジェクトのフォルダーでモジュールを初期化し、整形、テスト、ビルドを実行します。
go mod init example.com/hello
go fmt ./...
go test ./...
go buildgo mod tidyでgo.modとgo.sumを整えます。出所とライセンスも確認しましょう。ミニ課題:買い物合計
商品名、単価、個数を持つProduct構造体を作り、スライス内の合計額を関数で計算してください。
- 2商品以上の名前と小計を表示する
- 個数が1未満ならerrorを返す
- 想定した実行結果と一致するか確認する
次に学ぶこと
基礎を終えたら、次のテーマを小さなプログラムで一つずつ試しましょう。
- goroutineとchannel:複数の処理を協調させる並行処理
- context:タイムアウトやキャンセルを処理間で伝える
- net/http:標準ライブラリでWebサーバーやAPIを作る
- testing:テーブル駆動テスト、サブテスト、ベンチマークを学ぶ
最初の発展課題として、net/httpで一つのURLにJSONを返すAPIを作り、testingでレスポンスを確認すると、基礎の関数・構造体・エラー処理を組み合わせられます。
