Go 1.22 で面白いと思ったアップデート

# 概要

フューチャーのブログを読んでGo 1.22 についてのアップデートを読んでいて面白かった、すぐに利用できる部分のピックアップです。基本的にフューチャーのブログを参考にしていますので興味有る方は元記事読んでみてください！

追記：🚩 2024/02/07 リリースされました
https://go.dev/blog/go1.22

#  slice を連結する `Concat()` API が追加になった

refs: https://future-architect.github.io/articles/20240130a/
更新PR: ([#56353](https://github.com/golang/go/issues/56353))


``` go 
result := append(n1, append(n2, n3...)...)
```
↓
``` go
result := slices.Concat(n1, n2, n3)
```

で書けるようになった！:+1:

## 空スライスやnil のときはどうなる？
Golang ではスライスは参照型であり nil で表現することができますが、このときConcat をするとどうなるのか。
結果→エラーにはならず変化がない。nil同士を連結すると空スライスが返される

``` go
func main() {
	n1 := []int{1, 2}
	n2 := []int{10, 20}
	var n3 []int // nil で初期化
	result := slices.Concat(n1, n2, n3)
	fmt.Println(result) // [1 2 10 20]
}
```
playground: https://go.dev/play/p/lE2iKA8CIxY?v=gotip

``` go 
func main() {
	var n1, n2, n3 []int
	result := slices.Concat(n1, n2, n3)
	fmt.Println(result) // []
}
```
playground: https://go.dev/play/p/s8i7dovnC0G?v=gotip

となります。稀なケースですがnilを連結してもnil のまま扱いたい場合は少し注意が必要ですね。
Concat API のソースコードはこちら→　https://cs.opensource.google/go/go/+/master:src/slices/slices.go;l=502

## 感想
「Concat で書きましょう！」ってレビューができるとモダンなレビューになります。（笑）

---

#  HTTPルーティングの強化
Go1.22 リリース連載 HTTPルーティングの強化(**https://future-architect.github.io/articles/20240202a/)
- HTTPメソッドの指定が可能に

``` go 
mux.HandleFunc("GET /hello", func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello World")
})
```

- ワイルドカードの指定が可能に

``` go 
mux.HandleFunc("GET /items/{id}", func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "%s", r.PathValue("id"))
})
```
標準で手が届かない痛い部分だった。できるようになったかー！

## 感想
- 標準ライブラリでも使いやすくなっていてわりとこれでも良さそう
- ミドルウェアを自分で書かなきゃいけないのはキツイか…？

---

# int での Range がもっとシンプルにりようできるようになった　
ref: https://future-architect.github.io/articles/20240206a/

Range over integer というらしい。
以下のように書けるようになった

``` go
// 従来の書き方
for i := 0; i < 5; i++ {
            fmt.Println(i)
    }
```
↓
``` go
// Go 1.22 での新しい書き方(range over integer)
for i := range 5 {
		fmt.Println(i)
	}
```
※もちろん従来の書き方もできるよ!


## `for i := range -1` 、 `for i := range 0`  どうなる？

**結果**→**ループしない**
    
> For an integer value n, the iteration values 0 through n-1 are produced in increasing order. If n <= 0, the loop does not run any iterations.

`range over integer` の挙動としては
- range に渡された `n` が integer型の場合は
    - n > 0 ならば、0 から n-1 まで +1 だけインクリメントしながらループを継続する
    - n <= 0 ならば、ループしない
    (元記事より引用)


goplaygroundでの検証→ https://go.dev/play/p/lEPR3Xrh9gA?v=gotip
    - go dev branch にすると1.22 で遊べるよ！


## int以外、例えば`for i := range []string{"a","b","c"}`どうなる？

結果→インデックスのみが表示される。
これは従来と同じですね。この書き方自体は go 1.21 以下でもかけます。
他の対象でも同じです。


## 感想

Python みたいだな。
楽だけどちょっと初見殺し感がある例外的なコードなのはシンプルさが失われているようなきもするとか思ったけど、昨今のアップデートを見るとGoも柔軟になるように変化していっているんだろうな。

## おまけ
`  💡 range に入る第1返り値と第2返り値`
  感覚でやってたけど厳密な定義↓
  ``` go
Range expression                          1st value          2nd value

array or slice  a  [n]E, *[n]E, or []E    index    i  int    a[i]       E
string          s  string type            index    i  int    see below  rune
map             m  map[K]V                key      k  K      m[k]       V
channel         c  chan E, <-chan E       element  e  E
integer         n  integer type           value    i  see below
```
https://tip.golang.org/ref/spec#For_statements