はじめに
他の言語とは異なり、Go ではループ文にはキーワード "for" のみがあります。ただし、それは効率的で柔軟です。Go の for ループについて学んでみましょう。
ポイント:
- for ループ
- for range ループ
他の言語とは異なり、Go ではループ文にはキーワード "for" のみがあります。ただし、それは効率的で柔軟です。Go の for ループについて学んでみましょう。
ポイント:
前の基本データ構造のセクションでは、文字列は文字のコレクションであることを学びました。したがって、文字列内の特定の文字を取得するためにインデックスを使用できます。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 initialization; condition; post {
// コードブロック
}
初期化文は変数を初期化します。条件はブール値を返す必要があります。後処理文は各ループ反復で変数の値を変更します。具体的な例を見てみましょう。
~/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 に初期化し、各ループ反復で i
の値が 1 増加します。条件は i
の値が 10 未満の場合ループを続けることで、これはプログラムが 0 から 9 までの数字を出力することを意味します。
注:for ループでは、初期化文、条件文、後処理文はすべて省略可能です。これは、これらの文がなくても for ループが正常に機能することを意味します。
条件文のみがある場合、for ループは他の言語の "while" ループと同様に機能します。
次のコードは、条件文のみを使用して前のプログラムと同じ結果を得る例です。
package main
import "fmt"
func main() {
i := 0
for i < 10 {
fmt.Println(i)
i++
}
}
条件文のみがある場合、文を区切るために使用するセミコロン ;
を省略できることがわかります。
これで 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
ディレクトリに配置すること。ヒント:インデックスは 0 から始まります。
前のセクションでは、for ループの 3 つの文すべてが省略可能であることを述べました。どれも宣言しなかった場合、何が起こるでしょうか。実験してみましょう。
for.go
ファイルに次のコードを記入します。
package main
import "fmt"
func main() {
for {
fmt.Printf("1")
}
}
プログラムを実行します。
go run for.go
for ループの条件が宣言されていない場合、条件は true
と見なされ、ループは無限に続行することがわかります。
ヒント:Ctrl+C
を使ってプログラムを終了します。
条件文を宣言せずに特定の条件でループを抜けたい場合や条件文を記述できない場合、"break" キーワードを使用できます。これは、囲まれたループから即座に抜けるように強制します。
次のコードで "break" キーワードを使用して 23 個の "1" を出力するように for.go
ファイルを更新します。
package main
import "fmt"
func main() {
i := 0
for {
// 各ループ反復で i の値を 1 増やす
i++
fmt.Printf("1")
// i の値が 23 になったときにループを抜ける
if i == 23 {
break
}
}
}
"break" キーワードは、条件文のない for ループだけでなく、条件文のある for ループでも使用できます。"break" 条件が満たされると、条件文をスキップしてループを抜けます。
ループから即座に抜けるように強制する "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
このプログラムでは、for ループのコードブロックに条件文を追加しました。ループ変数の現在の値が 2 または 8 の場合、残りのコードをスキップして次のループ反復を開始します。したがって、出力には数字 2 と 8 は含まれません。
この実験では、for ループについて学びました。復習しましょう。