Go言語のrangeを使ったループ処理の書き方!スライス・マップを簡単に操作
生徒
「Go言語って、繰り返し処理をするときにrangeっていうのを使うって聞いたんですが、それって何なんですか?」
先生
「いい質問ですね。rangeは、スライスやマップのようなデータを順番に取り出して繰り返し処理を行うときに使う便利なキーワードなんです。」
生徒
「スライスとかマップって何ですか?初心者なので難しい言葉は苦手です…」
先生
「大丈夫ですよ。スライスは“箱の列”、マップは“名前付きの箱”のようなものです。詳しく説明しますので、順番に見ていきましょう!」
1. Go言語のrangeとは?
Go言語のrange(レンジ)は、スライスやマップなど「たくさんの値が入った入れ物」を、先頭から順番に取り出して処理するための書き方です。難しく考えなくても大丈夫で、「列にならんだデータを一つずつ取り出す合図」と覚えると理解しやすくなります。特に初心者にとって、手動で番号を増やすよりも読みやすく、安全に繰り返し処理を書けるのが大きな利点です。
スライスは「順番に並んだデータの集まり」で、例えるならラベルつきの引き出しが横に並んでいるイメージです。rangeを使うと、各要素の位置(インデックス)と中身(値)をペアで受け取り、自然な文章のように処理を書けます。まずは雰囲気をつかむために、シンプルな例を見てみましょう。
package main
import "fmt"
func main() {
fruits := []string{"りんご", "ばなな", "みかん"}
// rangeで「位置」と「中身」を順番に受け取る
for index, fruit := range fruits {
fmt.Println(index, fruit)
}
}
このコードでは、indexに「何番目か」、fruitに「その中身」が入り、0 りんご / 1 ばなな / 2 みかんのように表示されます。スライスに対するrangeは並び順どおりに要素を取り出すため、「先頭から順に処理したい」という用途にぴったりです。まずは「range=並んだデータを順番に扱う合図」という感覚をつかんでおきましょう。
2. スライスをrangeでループする方法
ここでは、スライスをrangeで「先頭から順番に」処理する基本を確認します。rangeは、自分でi++したり上限を気にしたりする必要がなく、位置(インデックス)と中身(値)をセットで取り出せるのがポイントです。まずは次のシンプルな例を実行して、画面にどう表示されるか体感してみましょう。
package main
import "fmt"
func main() {
fruits := []string{"りんご", "ばなな", "みかん"}
// rangeで「位置(index)」と「中身(value)」を順に受け取る
for index, fruit := range fruits {
fmt.Println(index, fruit)
}
}
range fruitsと書くことで、fruitsというスライスの要素を1つずつ取り出します。変数indexには位置番号(0から始まる数字)、fruitには実際の要素の値(ここでは果物の名前)が入ります。スライスは並び順が保たれるため、定義した順番どおりに処理が進みます。
0 りんご
1 ばなな
2 みかん
この書き方なら、配列やスライスの長さを数えるlen(...)を自分で使わなくても、最後の要素まで自動で回ってくれます。「番号も中身も使う」場面では上の形を覚えておけば十分です。番号が不要なときの省略テクニックは、次の節で紹介します。
3. インデックスが不要なときは「_(アンダースコア)」を使う
「番号はいらないから、中身だけ取り出したい」という場面では、使わない変数の受け取り先を_(ブランク識別子)にするとすっきり書けます。_は“捨てる箱”のような役割で、未使用変数エラーを避けつつ、読みやすいGo言語らしいループを実現できます。スライスの各要素だけを画面に出したい、というよくある用途で試してみましょう。
for _, fruit := range fruits {
fmt.Println(fruit) // インデックスは捨てて、値だけ使う
}
りんご
ばなな
みかん
このように_を使えば、インデックス(位置番号)を受け取らずに値だけに集中できます。逆に「位置だけ知りたい」という場合は、値側を_にして次のように書けます。状況に応じて“どちらか片方を捨てる”と覚えておくと、rangeを使ったスライスのループが読みやすく、安全に保てます。
for i, _ := range fruits {
fmt.Println(i) // 値は捨てて、インデックスだけ使う
}
0
1
2
Go言語のrangeは「インデックス」「値」の二つを同時に返すのが基本形です。_を上手に使い分けることで、不要な情報を受け取らずに済み、コードの意図がはっきり伝わるループ処理を書けるようになります。
4. マップ(map)をrangeでループする方法
マップとは、「名前付きの箱」のようなものです。例えば、「太郎さんは25歳」「花子さんは30歳」というように、キー(名前)と値(年齢)がセットになっています。
Go言語では、マップの中身をrangeで繰り返すことで、キーと値のペアを取り出すことができます。
ages := map[string]int{
"太郎": 25,
"花子": 30,
"次郎": 22,
}
for name, age := range ages {
fmt.Println(name, "は", age, "歳です")
}
太郎 は 25 歳です
花子 は 30 歳です
次郎 は 22 歳です
map[string]intの部分は、「文字列をキーとして、整数を値として持つマップ」を意味しています。初心者の方は「文字列=名前、整数=年齢」と理解すればOKです。
5. 値だけ使いたいときも「_」を使える
マップのキー(名前)は使わず、年齢だけを表示したい場合もあります。そのときもスライスと同じように_を使って、次のように書きます。
for _, age := range ages {
fmt.Println(age)
}
25
30
22
6. rangeを使ったループの注意点
rangeはとても便利ですが、使い方を間違えると意図しない動作になることもあります。たとえば、マップは順番が保証されていないため、ループのたびに表示順が変わる可能性があります。
これはGo言語の仕様ですので、「マップの順番はバラバラで当然」と覚えておきましょう。
7. rangeはfor文とセットで使う
Go言語では繰り返し処理にfor文を使います。C言語やJavaなどの他のプログラミング言語にはwhileやdo-whileというループもありますが、Go言語には基本的にforしかありません。そしてrangeはfor文と一緒に使うものです。
このように、Go言語ではfor + rangeというセットで、データのかたまりを簡単に操作できるのです。
まとめ
これまで、Go言語のrangeを使ったループ処理について、スライスとマップの使い方を中心にやさしく整理してきました。繰り返し処理という言葉は少し難しく聞こえることがありますが、実際には「並んだデータを一つずつ取り出す作業」です。スライスのように順番が決まっている入れ物、マップのように名前を付けて管理する入れ物、どちらにもrangeを使うことでとても自然な形で処理が書けます。特に、インデックスが不要なときに「_」を使える点は、初心者でも覚えやすく、無駄な変数が増えないので読みやすいコードになります。Go言語はシンプルで効率的な書き方ができることが魅力で、rangeを理解するとプログラムが一気に扱いやすくなります。
また、マップは順番が固定されていないという特徴があります。表示順が変わるのは失敗ではなく正しい動きという点も大切です。「繰り返し処理をすれば、必ず書いた順番に並ぶ」と考えると混乱してしまうので、マップは順番がバラバラという性質そのものを受け入れることがポイントになります。もし順番をそろえたい場合は、キーをスライスにまとめて並べ替える方法があります。こうした考え方は、実際のシステムで集計や検索を行うときにも役に立ちます。
rangeとforをセットで覚えることは、Go言語の基本的な書き方を正しく身につける近道になります。複雑な文法を使わなくても、自然な文章のように読みやすいコードが書けます。最初は小さなスライスやマップで練習し、思ったとおりに値が取り出せることを確認しながら慣れていくと、もっと大きなデータを扱うときにも応用できます。
サンプルプログラムでおさらい
最後に、rangeを使ってスライスとマップの両方をまとめて確認できるサンプルを用意しました。実際の動きを見ながら、取り出し方の違いやポイントを整理してみましょう。
package main
import "fmt"
func main() {
fruits := []string{"りんご", "ばなな", "みかん"}
ages := map[string]int{"太郎": 25, "花子": 30, "次郎": 22}
// スライスの全てを表示
for index, fruit := range fruits {
fmt.Println("番号:", index, "名前:", fruit)
}
// マップの全てを表示
for name, age := range ages {
fmt.Println(name, "は", age, "歳です")
}
// スライスで中身だけ取り出す
for _, fruit := range fruits {
fmt.Println("中身だけ:", fruit)
}
// マップで値だけ取り出す
for _, age := range ages {
fmt.Println("年齢だけ:", age)
}
}
rangeの書き方はどれも同じ形で、違う部分は取り出す中身だけです。こうして比べてみると、「ループ処理は難しい」という印象が大きく変わり、実際のプログラムにも活かしやすくなります。小さな例から書き始めると理解が進みますので、実際に試して動かしてみてください。
生徒
「rangeって、結局どんなときに使うのがいちばん良いんでしょうか?」
先生
「たくさんのデータを順番に取り出したいときですね。スライスのように順番があるデータでも、マップのように順番がないデータでも同じ形で書けるのが強みです。」
生徒
「アンダースコアを使う部分も便利でした。使わない変数をそのまま残すより、読みやすいと感じました。」
先生
「その通りです。不要な変数は無理に使う必要がありません。Go言語では読みやすさを大切にすることが、多くの場面で役に立ちます。」
生徒
「マップの順番がバラバラになる理由も理解できました。最初は間違いかと思っていましたが、仕様なんですね。」
先生
「その観点はとても大事です。仕様を知ることで、予想と違う動きに出会った時も落ち着いて原因を考えられます。今日学んだrangeは、実際の開発でもよく使うので、繰り返し練習するとさらに上達しますよ。」
生徒
「ありがとうございます。これでスライスとマップの扱いも前より自信がつきました!」