Skip to content

Commit e17b2f9

Browse files
authored
Merge pull request #1449 from future-architect/feature
template
2 parents 7a6db48 + e6f6361 commit e17b2f9

6 files changed

+275
-1
lines changed

source/_posts/20250127a_Go_1.24連載始まります&os.Root、WASMの最新のまとめ.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ lede: "恒例のGo新リリース記念連載が始まります。今回の1.24
2323
| 1/27 | インデックス+`os.Root`+WASM | 渋川 |
2424
| 1/28 | testing.Context | 真野さん |
2525
| 1/29 | [encoding/jsonのomitzero](/articles/20250129a/) | 島ノ江さん |
26-
| 1/30 | templateの新文法(イテレータ) | 大江さん |
26+
| 1/30 | [templateの新文法(イテレータ)](/articles/20250130a/) | 大江さん |
2727
| 1/31 | testing/synctest + 生成AI | 棚井さん |
2828
| 2/3 | strings関数 + encoding.TextAppender | 市川燿さん |
2929
| 2/4 | ツール管理回りの進化 | 辻さん |
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
---
2+
title: "Go 1.24リリース連載 templateの新文法(イテレータ)"
3+
date: 2025/01/30 00:00:00
4+
postid: a
5+
tag:
6+
- Go
7+
- Go1.24
8+
category:
9+
- Programming
10+
thumbnail: /images/20250130a/thumbnail.png
11+
author: 大江聖太郎,
12+
lede: "text/template`でのrange over func、range over intのサポート を取り上げます"
13+
---
14+
<img src="/images/20250130a/go1.24.png" alt="" width="800" height="484">
15+
16+
17+
# はじめに
18+
19+
TIG所属の大江です。[Go1.24リリース連載](/articles/20250127a/)の4本目です。
20+
21+
本記事では以下の内容を取り上げます。
22+
23+
- `text/template`でのrange over func、range over intのサポート
24+
25+
## アップデート内容
26+
27+
Go1.22で導入された`range over int`, Go1.23で導入された`range over func`が共に`text/template`パッケージで使えるようになりました。
28+
29+
以降では、これらの機能がどのように使えるかを見ていきます。
30+
31+
### range over int
32+
33+
指定された回数、同じ文字を繰り返すテンプレートを書く
34+
35+
#### Go1.23までの場合
36+
37+
テンプレートを使って同じ文字を10回繰り返す場合、以下のようにスライスや配列を生成してからテンプレートに渡す必要がありました。
38+
39+
```go
40+
package main
41+
42+
import (
43+
"log"
44+
"os"
45+
"text/template"
46+
)
47+
48+
func main() {
49+
numbers := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
50+
51+
// このピリオドは上で定義したnumbersのスライス
52+
tmpl := `{{range .}}Bonjour
53+
{{end}}`
54+
55+
t := template.Must(template.New("").Parse(tmpl))
56+
err := t.Execute(os.Stdout, numbers)
57+
if err != nil {
58+
log.Fatal(err)
59+
}
60+
}
61+
62+
/// 処理結果
63+
///
64+
/// Bonjour
65+
/// Bonjour
66+
/// Bonjour
67+
/// Bonjour
68+
/// Bonjour
69+
/// Bonjour
70+
/// Bonjour
71+
/// Bonjour
72+
/// Bonjour
73+
/// Bonjour
74+
75+
```
76+
77+
### Go1.24の場合
78+
79+
Go1.24では、range over intにより、以下のようにスライスや配列を用意せず直接テンプレート内で繰り返し回数を指定することが出来るようになりました。
80+
81+
``` go
82+
package main
83+
84+
import (
85+
"log"
86+
"os"
87+
"text/template"
88+
)
89+
90+
func main() {
91+
// 直接数字で繰り返し回数を指定
92+
tmpl := `{{range 10}}Bonjour
93+
{{end}}`
94+
95+
t := template.Must(template.New("").Parse(tmpl))
96+
err := t.Execute(os.Stdout, nil)
97+
if err != nil {
98+
log.Fatal(err)
99+
}
100+
}
101+
102+
/// 処理結果
103+
///
104+
/// Bonjour
105+
/// Bonjour
106+
/// Bonjour
107+
/// Bonjour
108+
/// Bonjour
109+
/// Bonjour
110+
/// Bonjour
111+
/// Bonjour
112+
/// Bonjour
113+
/// Bonjour
114+
115+
```
116+
117+
## range over func
118+
119+
マップの中の一部を抜き出してテンプレートを使って表示する
120+
121+
### Go1.23までの場合
122+
123+
以下では数字と文字の組み合わせの中から、偶数、3の倍数をそれぞれ抜き出し、テンプレートを使って表示します。
124+
Go1.23までは以下のように、それぞれの関数の戻り値として別のマップに代入するなどしてからテンプレートに渡す必要がありました。
125+
126+
``` go
127+
package main
128+
129+
import (
130+
"fmt"
131+
"log"
132+
"os"
133+
"text/template"
134+
)
135+
136+
func main() {
137+
numbers := map[int]string{
138+
1: "un",
139+
2: "deux",
140+
3: "trois",
141+
4: "quatre",
142+
5: "cinq",
143+
6: "six",
144+
7: "sept",
145+
8: "huit",
146+
9: "neuf",
147+
10: "dix",
148+
}
149+
150+
// このピリオドは下で定義したgetMultiples()の戻り値
151+
tmpl := `{{range $i, $c := .}}{{$i}}:{{$c}}
152+
{{end}}`
153+
154+
t := template.Must(template.New("").Parse(tmpl))
155+
fmt.Println("偶数")
156+
evenNumbers := getMultiples(numbers, 2)
157+
err := t.Execute(os.Stdout, evenNumbers)
158+
if err != nil {
159+
log.Fatal(err)
160+
}
161+
fmt.Println("\n3の倍数")
162+
threeMultiples := getMultiples(numbers, 3)
163+
err = t.Execute(os.Stdout, threeMultiples)
164+
if err != nil {
165+
log.Fatal(err)
166+
}
167+
}
168+
169+
func getMultiples(numbers map[int]string, divisor int) map[int]string {
170+
multiples := make(map[int]string, 10)
171+
for k, v := range numbers {
172+
if k%divisor == 0 {
173+
multiples[k] = v
174+
}
175+
}
176+
return multiples
177+
}
178+
179+
/// 処理結果
180+
/// ※Goのマップでは、反復処理の操作を行う際の順序は保証されていないので順序はランダム
181+
///
182+
/// 偶数
183+
/// 10:dix
184+
/// 2:deux
185+
/// 4:quatre
186+
/// 6:six
187+
/// 8:huit
188+
189+
/// 3の倍数
190+
/// 3:trois
191+
/// 6:six
192+
/// 9:neuf
193+
194+
```
195+
196+
### Go1.24の場合
197+
198+
新たに導入されたrange over funcを使えば、直接テンプレート内で関数を呼び出し、戻り値を表示することができます。
199+
なおrange over funcについては、[Go1.23連載の棚井さんの記事](https://future-architect.github.io/articles/20240718a/)を参考にさせていただきました。
200+
201+
```go
202+
package main
203+
204+
import (
205+
"fmt"
206+
"iter"
207+
"log"
208+
"os"
209+
"text/template"
210+
)
211+
212+
func main() {
213+
numbers := map[int]string{
214+
1: "un",
215+
2: "deux",
216+
3: "trois",
217+
4: "quatre",
218+
5: "cinq",
219+
6: "six",
220+
7: "sept",
221+
8: "huit",
222+
9: "neuf",
223+
10: "dix",
224+
}
225+
226+
// このピリオドは下で定義したgetMultiples()の戻り値
227+
tmpl := `{{range $i, $c := .}}{{$i}}:{{$c}}
228+
{{end}}`
229+
230+
t := template.Must(template.New("").Parse(tmpl))
231+
fmt.Println("偶数")
232+
err := t.Execute(os.Stdout, getMultiples(numbers, 2))
233+
if err != nil {
234+
log.Fatal(err)
235+
}
236+
fmt.Println("\n3の倍数")
237+
err = t.Execute(os.Stdout, getMultiples(numbers, 3))
238+
if err != nil {
239+
log.Fatal(err)
240+
}
241+
}
242+
243+
func getMultiples(numbers map[int]string, divisor int) iter.Seq2[int, string] {
244+
return func(yield func(int, string) bool) {
245+
for k, v := range numbers {
246+
if k%divisor == 0 {
247+
if !yield(k, v) {
248+
return
249+
}
250+
}
251+
}
252+
}
253+
}
254+
255+
/// 処理結果
256+
/// ※Goのマップでは、反復処理の操作を行う際の順序は保証されていないので数字の順序はランダム
257+
///
258+
/// 偶数
259+
/// 2:deux
260+
/// 4:quatre
261+
/// 10:dix
262+
/// 6:six
263+
/// 8:huit
264+
265+
/// 3の倍数
266+
/// 3:trois
267+
/// 6:six
268+
/// 9:neuf
269+
270+
```
271+
272+
# おわりに
273+
274+
以上、text/templateパッケージでのrange over int、range over funcについて紹介しました。近年のGoの反復処理のアップデートがさらに加速し、痒い所に手が届くようになった印象です。

source/images/20250129a/go1.24.png:Zone.Identifier

Whitespace-only changes.

source/images/20250129a/thumbnail.png:Zone.Identifier

Whitespace-only changes.

source/images/20250130a/go1.24.png

25 KB
Loading
7.97 KB
Loading

0 commit comments

Comments
 (0)