条件分岐
if文
age := 20
if age >= 20 {
fmt.Println("成人です")
} else if age >= 13 {
fmt.Println("ティーンエイジャーです")
} else {
fmt.Println("子供です")
}
if文の初期化文
// 変数宣言をif文に含める
if age := getAge(); age >= 20 {
fmt.Println("成人です")
} else {
fmt.Println("未成年です")
}
// age はこのスコープ外では使用不可
// エラーチェックでよく使用
if err := doSomething(); err != nil {
fmt.Println("エラー:", err)
return
}
switch文
day := 3
switch day {
case 1:
fmt.Println("月曜日")
case 2:
fmt.Println("火曜日")
case 3:
fmt.Println("水曜日")
case 6, 7:
fmt.Println("週末")
default:
fmt.Println("その他")
}
条件付きswitch
score := 85
switch {
case score >= 90:
fmt.Println("A")
case score >= 80:
fmt.Println("B")
case score >= 70:
fmt.Println("C")
case score >= 60:
fmt.Println("D")
default:
fmt.Println("F")
}
型switch
func describe(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("整数: %d\n", v)
case string:
fmt.Printf("文字列: %s\n", v)
case bool:
fmt.Printf("真偽値: %t\n", v)
default:
fmt.Printf("不明な型: %T\n", v)
}
}
describe(42) // 整数: 42
describe("hello") // 文字列: hello
describe(true) // 真偽値: true
fallthrough
n := 1
switch n {
case 1:
fmt.Println("1")
fallthrough // 次のcaseも実行
case 2:
fmt.Println("2")
case 3:
fmt.Println("3")
}
// 出力:
// 1
// 2
ループ
for文(基本)
// 基本のfor文
for i := 0; i < 5; i++ {
fmt.Println(i)
}
// 逆順
for i := 4; i >= 0; i-- {
fmt.Println(i)
}
// ステップを変更
for i := 0; i < 10; i += 2 {
fmt.Println(i) // 0, 2, 4, 6, 8
}
while相当
// Goにはwhileがない、forで代用
count := 0
for count < 5 {
fmt.Println(count)
count++
}
無限ループ
for {
fmt.Println("無限ループ")
break // breakで抜ける
}
range
// スライス
numbers := []int{1, 2, 3, 4, 5}
for index, value := range numbers {
fmt.Printf("index: %d, value: %d\n", index, value)
}
// インデックスのみ
for i := range numbers {
fmt.Println(i)
}
// 値のみ
for _, value := range numbers {
fmt.Println(value)
}
// マップ
scores := map[string]int{"太郎": 85, "花子": 92}
for key, value := range scores {
fmt.Printf("%s: %d\n", key, value)
}
// 文字列(ルーン)
for i, r := range "こんにちは" {
fmt.Printf("%d: %c\n", i, r)
}
break と continue
// break
for i := 0; i < 10; i++ {
if i == 5 {
break
}
fmt.Println(i) // 0, 1, 2, 3, 4
}
// continue
for i := 0; i < 10; i++ {
if i%2 == 0 {
continue
}
fmt.Println(i) // 1, 3, 5, 7, 9
}
ラベル付きbreak/continue
outer:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if i == 1 && j == 1 {
break outer // 外側のループを抜ける
}
fmt.Printf("i=%d, j=%d\n", i, j)
}
}
defer
関数終了時に実行される処理を登録します。
func example() {
defer fmt.Println("最後に実行")
fmt.Println("最初に実行")
}
// 出力:
// 最初に実行
// 最後に実行
複数のdefer(LIFO)
func example() {
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
}
// 出力:
// 3
// 2
// 1
deferでリソース解放
func readFile(path string) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close() // 関数終了時に必ず閉じる
// ファイル処理
return nil
}
panic と recover
func mayPanic() {
panic("エラーが発生しました")
}
func safeCall() {
defer func() {
if r := recover(); r != nil {
fmt.Println("回復しました:", r)
}
}()
mayPanic()
fmt.Println("これは実行されない")
}
func main() {
safeCall()
fmt.Println("プログラムは続行します")
}
// 出力:
// 回復しました: エラーが発生しました
// プログラムは続行します
実践例:素数判定
package main
import (
"fmt"
"math"
)
func isPrime(n int) bool {
if n < 2 {
return false
}
for i := 2; i <= int(math.Sqrt(float64(n))); i++ {
if n%i == 0 {
return false
}
}
return true
}
func main() {
for i := 1; i <= 100; i++ {
if isPrime(i) {
fmt.Println(i)
}
}
}
実践例:FizzBuzz
package main
import "fmt"
func main() {
for i := 1; i <= 30; i++ {
switch {
case i%15 == 0:
fmt.Println("FizzBuzz")
case i%3 == 0:
fmt.Println("Fizz")
case i%5 == 0:
fmt.Println("Buzz")
default:
fmt.Println(i)
}
}
}
まとめ
if文は初期化文を含められるswitchはbreak不要、fallthroughで次へ- 型switchで動的な型判定
forのみでwhile相当も表現rangeでコレクションをイテレートdeferで後処理を登録(LIFO順)panic/recoverで例外的状況に対応
次回は関数について学びます。