まえがき
Go言語のテンプレート機能は、WebアプリケーションやCLIツールなどでHTMLやテキストを動的に生成する際に非常に便利です。その中でも特に頻繁に使われるのが「range」という機能です。しかし、初心者の方にとっては少し分かりにくい部分もありますよね。
この記事では、Go言語のテンプレート機能の中でも特に重要な「range」の使い方を初心者向けに丁寧に解説します。基本的な使い方から実用的な例、そして初心者がつまずきやすいポイントまで詳しく見ていきましょう。
Go言語のテンプレート機能の基本的な使い方については下記記事をお読みください。
Go言語のテンプレート機能を初心者向けに解説
Goテンプレートのrangeとは?基本的な使い方を理解しよう
Go言語のテンプレート機能における「range」は、配列やスライス、マップなどのコレクションを繰り返し処理するための機能です。テンプレート内で繰り返し処理を行うことで、動的にデータを表示できます。
基本的な書き方は以下の通りです。
| 1
2
3
 | {{range .Items}}
  {{.}}
{{end}}
 | 
この例では、テンプレートに渡されたデータの中の「Items」というスライスや配列を順番に取り出して表示しています。
例えば、以下のようなデータをテンプレートに渡した場合を考えてみましょう。
| 1
2
3
4
5
 | data := struct {
    Items []string
}{
    Items: []string{"りんご", "バナナ", "みかん"},
}
 | 
テンプレートを実行すると次のようになります。
Goテンプレートのrangeを実用的に使うための書き方例
実際の開発現場では、単純な配列だけでなく、構造体のスライスやマップを扱うことが多いです。ここでは、構造体のスライスをrangeで処理する例を見てみましょう。
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
 | type User struct {
    Name string
    Age  int
}
data := struct {
    Users []User
}{
    Users: []User{
        {"もふ太郎", 3},
        {"にゃん子", 5},
        {"ぽち", 2},
    },
}
 | 
テンプレート側の記述は以下のようになります。
| 1
2
3
 | {{range .Users}}
  名前: {{.Name}}, 年齢: {{.Age}}
{{end}}
 | 
実行すると以下のような結果になります。
| 1
2
3
 | 名前: もふ太郎, 年齢: 3
名前: にゃん子, 年齢: 5
名前: ぽち, 年齢: 2
 | 
また、マップを使った例も見てみましょう。
| 1
2
3
4
5
6
7
8
9
 | data := struct {
    Fruits map[string]int
}{
    Fruits: map[string]int{
        "りんご":  3,
        "バナナ":  5,
        "みかん":  2,
    },
}
 | 
テンプレート側の記述は以下のようになります。
| 1
2
3
 | {{range $key, $value := .Fruits}}
  {{$key}}は{{$value}}個あります。
{{end}}
 | 
実行結果は以下のようになります。
| 1
2
3
 | りんごは3個あります。
バナナは5個あります。
みかんは2個あります。
 | 
Goテンプレートのrangeを使うメリットとは?
Goテンプレートのrangeを使うメリットは主に以下の通りです。
- 配列やマップなどのデータを簡単に繰り返し表示できる
- コードがシンプルで読みやすくなる
- データの変更に柔軟に対応できるため、メンテナンス性が向上する
特にWebアプリケーションなどで動的にデータを表示する際には、rangeを使うことでコードが簡潔になり、開発効率が大幅に向上します。
Goテンプレートのrangeを使う際の注意点と初心者がつまずきやすいポイント
rangeを使う際に初心者がつまずきやすいポイントをいくつか挙げておきます。
1. ドット(.)の意味を理解する
range内での「.」は、現在処理している要素を指します。rangeの外側の「.」とは意味が異なるため、混乱しないように注意しましょう。
2. 空の配列やマップを処理する場合
空の配列やマップをrangeで処理すると、何も表示されません。空の場合に特別なメッセージを表示したい場合は、以下のようにelseを使うことができます。
| 1
2
3
4
5
 | {{range .Items}}
  {{.}}
{{else}}
  アイテムがありません。
{{end}}
 | 
3. インデックスを取得したい場合
配列やスライスのインデックスを取得したい場合は、以下のように書きます。
| 1
2
3
 | {{range $index, $element := .Items}}
  {{$index}}番目は{{$element}}です。
{{end}}
 | 
実行結果は以下のようになります。
| 1
2
3
 | 0番目はりんごです。
1番目はバナナです。
2番目はみかんです。
 | 
各解説のプログラム全体
基本的な使い方(配列の例)
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
 | package main
import (
	"os"
	"text/template"
)
func main() {
	data := struct {
		Items []string
	}{
		Items: []string{"りんご", "バナナ", "みかん"},
	}
	const tpl = `{{range .Items}}  {{.}}
{{end}}`
	t, _ := template.New("example").Parse(tpl)
	t.Execute(os.Stdout, data)
}
 | 
実用的な使い方(構造体のスライス)
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 | package main
import (
	"os"
	"text/template"
)
type User struct {
	Name string
	Age  int
}
func main() {
	data := struct {
		Users []User
	}{
		Users: []User{
			{Name: "もふ太郎", Age: 3},
			{Name: "にゃん子", Age: 5},
			{Name: "ぽち", Age: 2},
		},
	}
	const tpl = `{{range .Users}} 名前: {{.Name}}, 年齢: {{.Age}}
{{end}}`
	t, _ := template.New("users").Parse(tpl)
	t.Execute(os.Stdout, data)
}
 | 
実用的な使い方(マップの例)
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 | package main
import (
	"os"
	"text/template"
)
func main() {
	data := struct {
		Fruits map[string]int
	}{
		Fruits: map[string]int{
			"りんご": 3,
			"バナナ": 5,
			"みかん": 2,
		},
	}
	const tpl = `{{range $key, $value := .Fruits}} {{$key}}は{{$value}}個あります。
{{end}}`
	t, _ := template.New("fruits").Parse(tpl)
	t.Execute(os.Stdout, data)
}
 | 
Goテンプレートのrangeを使う際の注意点と初心者がつまずきやすいポイント
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 | package main
import (
	"os"
	"text/template"
)
func main() {
	// Items: 通常のデータ、EmptyItems: 空のスライス(elseを使う例)
	data := struct {
		Items      []string
		EmptyItems []string
	}{
		Items:      []string{"りんご", "バナナ", "みかん"},
		EmptyItems: []string{},
	}
	const tpl = `
【通常のrange (ドットの使い方)】
{{range .Items}}・{{.}}
{{end}}
【空の配列の場合】
{{range .EmptyItems}}・{{.}}
{{else}}※データがありません{{end}}
【インデックス付き表示】
{{range $index, $element := .Items}}{{$index}}番目は{{$element}}です。
{{end}}
`
	t, err := template.New("example").Parse(tpl)
	if err != nil {
		panic(err)
	}
	t.Execute(os.Stdout, data)
}
 | 
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
 | 【通常のrange (ドットの使い方)】
・りんご
・バナナ
・みかん
【空の配列の場合】
※データがありません
【インデックス付き表示】
0番目はりんごです。
1番目はバナナです。
2番目はみかんです。
 | 
あとがき
今回はGo言語のテンプレート機能の中でも特に重要な「range」の使い方について、初心者向けに詳しく解説しました。rangeを使いこなせるようになると、テンプレートを使った動的なデータ表示がとても簡単になります。
最初は少し難しく感じるかもしれませんが、この記事を参考にしてぜひ実際に手を動かして試してみてください。