紹介
コンピュータープログラミングにおいて、ループは、コードを繰り返して実行する構文を持つ構造であり、一般的に、いくつかの条件が満たされるまで続く。コンピュータープログラミングでのループの使用により、同じような作業を自動化し、何度も繰り返すことができます。たとえば、処理する必要があるファイルのリストがあったり、記事の行数を数えたいときには、そのような問題を解決するためにコード内のループを使用します。
Go言語では、for
ループを使って、 loop counterやloop variableに基づいてコードを繰り返して実行することができます。while
、do
などの他のプログラミング言語のように複数のループ構文を持つものではなく、Goにはfor
ループしか存在しません。これにより、あなたのコードがより明確で可読性が高くなり、同じループ構造を実現するための複数の戦略を心配する必要がなくなります。開発中の知的負荷を軽減し、他の言語よりもエラーに対する抵抗力が高まることから、読む人にとってもより良い結果をもたらします。
このチュートリアルで、Goのfor
ループの仕組みを学ぶことができます。それには、その使用の3つの主要な変形が含まれます。まず、異なる種類のfor
ループを作成する方法を見ていき、その後、Goでの連続的なデータ型をループしていく方法を学びます。最後に、嵌套されたループの使用方法を説明します。
ForClauseと条件ループの宣言
多様な使用例を考慮するために、Goでfor
ループを作成するための3つの異なる方法があり、それぞれ独自の機能を持っています。これらはfor
ループを条件として作成する、ForClauseを使用する、またはRangeClauseを使用することです。この節で、ForClauseと条件変数の宣言と使用法を説明します。
まず、ForClauseを使用したfor
ループの例を見てみましょう。
ForClauseループは、初期ステートメント、条件、そして後置ステートメントを持つように定義されています。これらは以下の構文で並べられます。
for [ Initial Statement ] ; [ Condition ] ; [ Post Statement ] {
[Action]
}
前述のコンポーネントが何を行うのか説明するために、ForClause構文を使用して指定された範囲の値をインクリメントしながらfor
ループを見てみましょう。
このループを分解し、各部分を特定していきましょう。
ループの最初の部分はi := 0
です。これは初期ステートメントです。
for i := 0; i < 5; i++ {
fmt.Println(i)
}
これはi
という変数を宣言し、初期値を0
に設定することを示しています。
次に条件があります。
for i := 0; i < 5; i++ {
fmt.Println(i)
}
この条件では、i
が5
以下であれば、ループを続けることを指定しています。
最後に、後置ステートメントがあります。
for i := 0; i < 5; i++ {
fmt.Println(i)
}
postステートメントでは、i
という루프変数をi++
を使用して每次の迭代時に1つ上にincrementします。
このプログラムを実行すると、以下のような出力が表示されます:
Output0
1
2
3
4
このループは5回実行されました。最初にi
を0
に設定し、次にi
が5
以下かどうかチェックしました。i
の値は5
以下であるため、ループが実行され、fmt.Println(i)
のアクションが実行されました。ループが完了した後、i++
のpostステートメントが呼び出され、i
の値は1つ上に増やされました。
注意:プログラミングでは指数0から始めることが多いから、5の数が印字されたのは0から4までの範囲であることに注意してください。
0から始めるのではなく、任意の値を初期式に割り当て、postステートメントで任意の値までに停止することもできます。これにより、任意の必要な範囲をループすることができます:
ここで、迭代は20(含まれる)から25(含まれない)まで行われるため、以下のような出力が表示されます:
Output20
21
22
23
24
postステートメントを使用して異なる値で増分することもできます。他の言語のstep
と似たことです:
まず、POSTステートメントを正の値と使用してみましょう:
for i := 0; i < 15; i += 3 {
fmt.Println(i)
}
この場合、for
ループは0から15までの数値を出力しますが、3の增量であるため、3つごとの数値しか出力されません。以下のように表示されます:
Output0
3
6
9
12
私たちは、後置声明の引数にネガティブの値を使用して、後退的に繰り返すこともできますが、初期ステートメントと条件引数を適切に調整する必要があります。
ここで、初期値を100
に設定し、条件をi < 0
に設定して0
まで行くようにし、後置ステートメントで10つの値を減らす-=
运算子を使用します。ループは100
から始まり、0
まで行き、各イテレーションで10つの値を減少させます。出力にこれが反映されることがわかります。
Output100
90
80
70
60
50
40
30
20
10
また、初期ステートメントと後置ステートメントをfor
スyntaxから除外し、条件だけを使用することもできます。これは条件ループと呼ばれます。
i := 0
for i < 5 {
fmt.Println(i)
i++
}
この回、変数i
をfor
ループの前の行の中で別々に宣言しました。ループには条件の節だけがあり、i
が5
以下かどうかを確認します。条件がtrue
と評価される間、ループはイテレーションを続けます。
特定の任务を完了するために必要な繰り返し回数を知らない場合もあります。その場合、すべてのステートメントを省略し、break
キーワードを使用して実行を終了することができます。
for {
if someCondition {
break
}
// ここに动作を行います
}
この例では、不确定な大きさの構造(例えばバッファ)から読み取る際に、完了するまでを知らないような場合に使われるかもしれません。
前のコードでは、`buf :=bytes.NewBufferString(“one\ntwo\nthree\nfour\n”)`と宣言したバッファにデータが含まれています。缓冲区が読み終わる時間を知らないため、for
文に条件をつけません。for
文の内部で、`line, err := buf.ReadString(‘\n’)`を使用して缓冲区から一行を読み取り、缓冲区から読み取ることに失敗したか否かを確認します。失敗した場合、そのエラーを解決し、`break`キーワードを使用してfor文を終了する。これらのbreak
ポイントで、for文を停止する条件を含む必要はありません。
この節で、ForClauseのループを宣言し、既知の範囲の値を迭代する方法を学びました。また、特定の条件を満たすまでに迭代するConditionループの使用方法も学びました。次に、RangeClauseが順序的なデータ型を迭代するための使用方法を学びます。
RangeClauseを使用して順序的なデータ型をループする
Go言語では、for
ループを使用して、slice、配列、stringなどの連続的なまたは集合的なデータ型の要素をイテレートすることが一般的です。これをより簡単にするために、for
ループをRangeClause 構文とともに使用することができます。ForClause 構文を使用して連続的なデータ型をループしても構いませんが、RangeClauseはより清潔で、読むのが容易です。
RangeClauseを使用する前に、ForClause 構文を使用してスライスをイテレートする方法を見ていきましょう:
package main
import "fmt"
func main() {
sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
for i := 0; i < len(sharks); i++ {
fmt.Println(sharks[i])
}
}
これを実行すると、以下の出力が表示されます。これはスライスの各要素を印刷します:
Outputhammerhead
great white
dogfish
frilled
bullhead
requiem
今、同じ操作を行うためにRangeClauseを使用してみましょう:
package main
import "fmt"
func main() {
sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
for i, shark := range sharks {
fmt.Println(i, shark)
}
}
この場合、リストの各アイテムを印刷しています。変数i
およびshark
を使用したとしても、他の有効な変数名を変数に割り当てることができ、同じ出力が得られます:
Output0 hammerhead
1 great white
2 dogfish
3 frilled
4 bullhead
5 requiem
スライス上でrange
を使用すると、常に2つの値を返します。最初の値は、現在のループのイテレーションにおけるインデックスであり、2番目の値はそのインデックスにある値です。この場合、最初のイテレーションでは、インデックスは0
であり、そのインデックスの値はhammerhead
でした。
sometimes、sliceの要素値を取り出したいときは、索引を使用しないでください。前のコードを変更して、値だけをprint outするようにしたら、compile timeエラーが発生します:
package main
import "fmt"
func main() {
sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
for i, shark := range sharks {
fmt.Println(shark)
}
}
Outputsrc/range-error.go:8:6: i declared and not used
becausei
is declared in thefor
loop, but never used, the compiler will respond with the error ofi declared and not used
. This is the same error that you will receive in Go anytime you declare a variable and don’t use it.
Because of this, Go has theblank identifier(underscore)(_
). In afor
loop, you can use the blank identifier to ignore any value returned from therange
keyword. In this case, we want to ignore the index, which is the first argument returned.
package main
import "fmt"
func main() {
sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
for _, shark := range sharks {
fmt.Println(shark)
}
}
Outputhammerhead
great white
dogfish
frilled
bullhead
requiem
This output shows that thefor
loop iterated through the slice of strings, and printed each item from the slice without the index.
You can also userange
to add items to a list:
package main
import "fmt"
func main() {
sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
for range sharks {
sharks = append(sharks, "shark")
}
fmt.Printf("%q\n", sharks)
}
Output['hammerhead', 'great white', 'dogfish', 'frilled', 'bullhead', 'requiem', 'shark', 'shark', 'shark', 'shark', 'shark', 'shark']
Here, we have added a placeholder string of"shark"
for each item of the length of thesharks
slice.
Notice that we didn’t have to use the blank identifier_
to ignore any of the return values from therange
operator. Go allows us to leave out the entire declaration portion of therange
statement if we don’t need to use either of the return values.
We can also use therange
operator to fill in values of a slice:
package main
import "fmt"
func main() {
integers := make([]int, 10)
fmt.Println(integers)
for i := range integers {
integers[i] = i
}
fmt.Println(integers)
}
この例では、slice `integers` は10個の空値を初期化しますが、for
ループは繰り返しているindexに対応する値を全て設定します:
Output[0 0 0 0 0 0 0 0 0 0]
[0 1 2 3 4 5 6 7 8 9]
初回で slice `integers` の値をprintした時、全ての値は0です。次に、loopで各indexをiterateして、それぞれに現在のindex値をsetします。次回 print 時、`integers` の値は全て0から0~9まで変更されています:
我们也可以使用 range
操作符来迭代字符串中的每个字符:
OutputS
a
m
m
y
当迭代 映射 时,range
会返回 键 和 值:
Outputcolor: blue
location: ocean
name: Sammy
animal: shark
注意:重要的是要注意,map返回的顺序是随机的。每次运行这个程序,你可能会得到不同的结果。
现在我们已经学会了如何使用 range
和 for
循环来迭代序列数据,让我们来看一下如何使用嵌套循环。
嵌套 for 循环
Go言語でも他のプログラミング言語と同様にネストされたループを使用できます。ネストとは、一つの構造の中に別の構造を入れ替えることを指します。この場合、ネストされたループは、他のループの中で発生するループです。これは、データセットのすべての要素に対してループされる动作を実行したい場合に有用です。
ネストされたループは、ネストされたif
文と構造的に似ています。それは以下のように構築されます。
for {
[Action]
for {
[Action]
}
}
プログラムはまず外側のループに遭遇し、最初のイテレーションを実行します。この最初のイテレーションは、内部的なネストされたループをトリガーし、完了まで実行します。次に、プログラムは外側のループの頂点に戻り、2番目のイテレーションを完了し、再び内部的なネストされたループをトリガーします。再び、内部的なネストされたループは完了し、プログラムは外側のループの頂点に戻ります。これが完了するまでまたはbreak句などのステートメントがプロセスを破壊するまでに繰り返されます。
次に、より詳細にネストされたfor
ループを実装してみましょう。この例では、外側のループはnumList
という整数のスライスをイテレートし、内部のループはalphaList
という文字列のスライスをイテレートします。
このプログラムを実行すると、以下の出力が表示されます。
Output1
a
b
c
2
a
b
c
3
a
b
c
外部ループは1回目のiterationで1
を出力し、それが内部ループを触发する。内部ループは次々にa
、b
、c
を连续に出力します。外部ループの顶端に戻って来た後、2
を出力し、再度内部ループを全て出力します(a
、b
、c
) など。
内蔵されたfor
loopは、内蔵されたsliceをiterateすることができます。単一のfor
loopを使用していた場合、外部listは1つずつ出力されます:
Output[0 1 2]
[-1 -2 -3]
[9 8 7]
要は、内部slicesの個別itemを取り出すには、nestedfor
loopを使う必要があります:
Output0
1
2
-1
-2
-3
9
8
7
このように、nestedfor
loopを使用することで、外部slices内の各itemをiterateできます。
結論
本教程ではGoで繰り返し処理を行う方法を見ていました。私たちは3種類のfor
loopの变体を見ていましたから、それらを使う時の違いも知っておくと良いです。繰り返し処理を制御するには、break
やcontinue
ステンションを使うこともできます。詳細はGoで繰り返し処理を行う時に break 和 continue ステンションを使うを読みましょう。
Source:
https://www.digitalocean.com/community/tutorials/how-to-construct-for-loops-in-go