はじめに
他のプログラミング言語とは異なり、Go 言語のループ処理には for キーワードしか存在しません。しかし、この for ループは非常に効率的で柔軟性に富んでいます。この実験では、Go における for ループについて学んでいきましょう。
習得する知識:
- for ループ
- for range ループ
文字列内の文字
基本的なデータ構造に関する前のセクションで、文字列は文字の集合であることを学びました。そのため、インデックス(添字)を使用して文字列内の特定の文字を取得することができます。まず、string.go ファイルを作成し、以下のコードを記述してみましょう。
cd ~/project
touch string.go
package main
import "fmt"
func main() {
s := "labex"
// インデックスを使用して文字列内の各文字にアクセスする
fmt.Println(s[0], s[1], s[2], s[3], s[4])
// 文字として出力する
fmt.Printf("%c %c %c %c %c\n", s[0], s[1], s[2], s[3], s[4])
}
プログラムを実行します。
go run string.go
出力結果は以下の通りです。
108 97 98 101 120
l a b e x
このプログラムでは、"labex" という文字列を格納する変数を用意し、インデックスを使って各文字にアクセスしています。最初の出力では、実際の文字ではなく数値が表示されていることがわかります。
ASCII コード表と照らし合わせると、これらの数値が実際の文字に対応していることが確認できます。例えば、ASCII 表では "108" は "l" に対応しています。
これは、文字が実際には「UTF-8」エンコーディングに基づいた数値として格納されているためです。「UTF-8」は「ASCII」と互換性があるため、文字 "l" の位置には数値エンコーディングである "108" が保持されています。
文字として出力したい場合は、fmt.Printf 関数の %c エスケープシーケンスを使用します。コードの 2 行目のように記述することで、数値エンコーディングが文字に変換されて出力されます。
string.go ファイルのように文字列の各文字にアクセスする場合、毎回インデックスを指定するのは非常に手間がかかります。特に数百、数千のデータを扱う場合には現実的ではありません。このような場合に for ループを使用すると、効率的に処理を行うことができます。
For ループの構文
ループは、特定の条件に基づいてプログラムを繰り返し実行します。for ループ文の基本構文を見てみましょう。
for 初期化文; 条件式; 後処理文 {
// コードブロック
}
初期化文は変数を初期化します。条件式は真偽値(boolean)を返す必要があります。後処理文は、ループの各繰り返しの最後に変数の値を更新します。具体的な例を見てみましょう。
~/project ディレクトリに for.go ファイルを作成し、以下の内容を記述します。
cd ~/project
touch for.go
package main
import "fmt"
func main() {
// 0 から 9 までの数字を出力する
for i := 0; i < 10; i++ {
fmt.Println(i)
}
}
プログラムを実行します。
go run for.go
出力結果は以下の通りです。
0
1
2
3
4
5
6
7
8
9
このプログラムでは、まず一時変数 i を 0 に初期化し、ループが 1 回回るごとに i の値を 1 ずつ増やしています。条件式は i < 10 なので、i が 10 未満の間ループが継続され、結果として 0 から 9 までの数字が出力されます。
注意: for ループにおいて、初期化文、条件式、後処理文はすべて省略可能です。つまり、これらがなくても for ループは動作します。
条件式のみを記述した場合、for ループは他の言語における "while" ループと同じように機能します。
以下のコードは、条件式のみを使用して前のプログラムと同じ結果を実現する例です。
package main
import "fmt"
func main() {
i := 0
for i < 10 {
fmt.Println(i)
i++
}
}
条件式のみを記述する場合、各文を区切るためのセミコロン ; を省略できることがわかります。
For ループの活用
for ループの構文を理解したところで、最初のプログラム string.go を for ループを使って書き換えてみましょう。
package main
import "fmt"
func main() {
s := "labex"
for i := 0; i < len(s); i++ {
fmt.Printf("%d %c\n", int(s[i]), s[i])
}
}
プログラムを実行します。
go run string.go
出力結果は以下の通りです。
108 l
97 a
98 b
101 e
120 x
クイズ
for ループの理解を深めるために、クイズに挑戦しましょう。
for2.go ファイルを作成してください。タスクは、文字列 "labex" の各文字を逆順に出力することです。
期待される出力:
x
e
b
a
l
要件:
for2.goファイルは~/projectディレクトリに配置すること。forループを使用して結果を実現すること。
ヒント: インデックスは 0 から始まります。
break キーワード
前のセクションで、for ループの 3 つの要素はすべて省略可能であると説明しました。もし何も宣言しなかったらどうなるでしょうか?実験してみましょう。
for.go ファイルに以下のコードを記述します。
package main
import "fmt"
func main() {
for {
fmt.Printf("1")
}
}
プログラムを実行します。
go run for.go
for ループに条件が宣言されていない場合、条件は常に true とみなされ、ループは無限に繰り返されます。
ヒント: プログラムを終了するには Ctrl+C を押してください。
条件式を宣言せずに、あるいは特定の条件でループを抜けたい場合は、break キーワードを使用します。これにより、現在実行中のループを即座に終了させることができます。
for.go ファイルを以下のコードに更新してください。break キーワードを使用して、"1" を 23 個出力した後に終了します。
package main
import "fmt"
func main() {
i := 0
for {
// ループごとに i の値を 1 増やす
i++
fmt.Printf("1")
// i の値が 23 になったらループを抜ける
if i == 23 {
break
}
}
}
break キーワードは、条件式のないループだけでなく、通常の条件式があるループでも使用できます。break の条件が満たされると、ループの条件式に関わらず即座にループを終了します。
continue キーワード
ループを即座に終了させる break キーワードに加えて、continue キーワードもあります。これは、現在のループ回の残りの処理をスキップして、次の繰り返し(イテレーション)を即座に開始するために使用されます。
continue キーワードの使い方は break と似ていますが、機能が異なります。
for.go ファイルを更新して、2 と 8 の数字をスキップするようにしてみましょう。
package main
import "fmt"
func main() {
for i := 0; i < 10; i++ {
if i == 2 || i == 8 {
continue
}
fmt.Println(i)
}
}
プログラムを実行します。
go run for.go
出力結果は以下の通りです。
0
1
3
4
5
6
7
9
このプログラムでは、ループ内のコードブロックに条件文を追加しました。ループ変数の値が 2 または 8 の場合、それ以降の処理(この場合は fmt.Println)をスキップして次のループを開始します。そのため、出力には 2 と 8 が含まれません。
まとめ
この実験では、for ループについて学びました。内容を復習しましょう。
forループの 3 つのパラメータはすべて省略可能です。breakキーワードを使用すると、現在のループを終了できます。continueキーワードを使用すると、現在の繰り返しをスキップして次の繰り返しを開始できます。



