golangci-lintでジェネリクスが使えるようになった

golangci-lintが、 `v1.45.0` (投稿時点の最新版)でGo1.18の新構文（ジェネリクスやany等）に対応しました :tada:
これで心おきなくジェネリクスが使えます！

https://github.com/golangci/golangci-lint/releases/tag/v1.45.0

早速 [issueでの紹介手順](https://github.com/golangci/golangci-lint/pull/2438) に従ってリンターをかけてみました。
（現在進行形で対応が進んでいるので、最新の状況については ~~この記事より~~ issueでの確認をおすすめします）

# 準備

`.golangci.yml` に以下の2行を足すだけです。

```yaml:.golangci.yml
run:
    go: 1.18
```

（ちなみに指定しない場合Go1.17までのモードで起動しクラッシュしました）

```bash
$ golangci-lint run
ERRO [runner] Panic: unused: package "main" (isInitialPkg: true, needAnalyzeSource: true): T: goroutine 747 ...
WARN [runner] Can't run linter goanalysis_metalinter: goanalysis_metalinter: unused: package "main" (isInitialPkg: true, needAnalyzeSource: true): T
ERRO Running error: 1 error occurred:
        * can't run linter goanalysis_metalinter: goanalysis_metalinter: unused: package "main" (isInitialPkg: true, needAnalyzeSource: true): T
```

# 使ってみる

以下の新構文を入れたサンプルコードにリンターをかけます。

- ジェネリック関数
- `any`
- `comparable`

```go:main.go
package main

import "fmt"

func myGenerics[T comparable](a, b T) bool {
	return a == b
}

func main() {
	var _ any
	fmt.Println(myGenerics("foo", "bar"))
}
```

リンターはすべて有効化します。

```yaml:.golangci.yml
run:
  go: 1.18
linters:
  enable-all: true
```

実行成功しました。`forbidigo` に怒られていますが、`Println` を使っているので想定通りです。

```bash
$ golangci-lint run
WARN [runner] The linter 'interfacer' is deprecated (since v1.38.0) due to: The repository of the linter has been archived by the owner.
WARN [runner] The linter 'maligned' is deprecated (since v1.38.0) due to: The repository of the linter has been archived by the owner.  Replaced by govet 'fieldalignment'.
WARN [runner] The linter 'golint' is deprecated (since v1.41.0) due to: The repository of the linter has been archived by the owner.  Replaced by revive.
WARN [runner] The linter 'scopelint' is deprecated (since v1.39.0) due to: The repository of the linter has been deprecated by the owner.  Replaced by exportloopref.
WARN [linters context] bodyclose is disabled because of go1.18. If you are not using go1.18, you can set `go: go1.17` in the `run` section. You can track the evolution of the go1.18 support by following the https://github.com/golangci/golangci-lint/issues/2649.
WARN [linters context] contextcheck is disabled because of go1.18. If you are not using go1.18, you can set `go: go1.17` in the `run` section. You can track the evolution of the go1.18 support by following the https://github.com/golangci/golangci-lint/issues/2649.
WARN [linters context] gosimple is disabled because of go1.18. If you are not using go1.18, you can set `go: go1.17` in the `run` section. You can track the evolution of the go1.18 support by following the https://github.com/golangci/golangci-lint/issues/2649.
WARN [linters context] nilerr is disabled because of go1.18. If you are not using go1.18, you can set `go: go1.17` in the `run` section. You can track the evolution of the go1.18 support by following the https://github.com/golangci/golangci-lint/issues/2649.
WARN [linters context] noctx is disabled because of go1.18. If you are not using go1.18, you can set `go: go1.17` in the `run` section. You can track the evolution of the go1.18 support by following the https://github.com/golangci/golangci-lint/issues/2649.
WARN [linters context] rowserrcheck is disabled because of go1.18. If you are not using go1.18, you can set `go: go1.17` in the `run` section. You can track the evolution of the go1.18 support by following the https://github.com/golangci/golangci-lint/issues/2649.
WARN [linters context] sqlclosecheck is disabled because of go1.18. If you are not using go1.18, you can set `go: go1.17` in the `run` section. You can track the evolution of the go1.18 support by following the https://github.com/golangci/golangci-lint/issues/2649.
WARN [linters context] staticcheck is disabled because of go1.18. If you are not using go1.18, you can set `go: go1.17` in the `run` section. You can track the evolution of the go1.18 support by following the https://github.com/golangci/golangci-lint/issues/2649.
WARN [linters context] stylecheck is disabled because of go1.18. If you are not using go1.18, you can set `go: go1.17` in the `run` section. You can track the evolution of the go1.18 support by following the https://github.com/golangci/golangci-lint/issues/2649.
WARN [linters context] tparallel is disabled because of go1.18. If you are not using go1.18, you can set `go: go1.17` in the `run` section. You can track the evolution of the go1.18 support by following the https://github.com/golangci/golangci-lint/issues/2649.
WARN [linters context] unparam is disabled because of go1.18. If you are not using go1.18, you can set `go: go1.17` in the `run` section. You can track the evolution of the go1.18 support by following the https://github.com/golangci/golangci-lint/issues/2649.
WARN [linters context] wastedassign is disabled because of go1.18. If you are not using go1.18, you can set `go: go1.17` in the `run` section. You can track the evolution of the go1.18 support by following the https://github.com/golangci/golangci-lint/issues/2649.
WARN [linters context] unused is disabled because of go1.18. If you are not using go1.18, you can set `go: go1.17` in the `run` section. You can track the evolution of the go1.18 support by following the https://github.com/golangci/golangci-lint/issues/2649.
main.go:11:2: use of `fmt.Println` forbidden by pattern `^(fmt\.Print(|f|ln)|print|println)$` (forbidigo)
        fmt.Println(myGenerics("foo", "bar"))
```

一部のリンターが無効化されているという警告がでていますが、これは静的単一代入(SSA)の検査がジェネリクス未対応なためのようです。

- 無効化されているリンター一覧

https://github.com/golangci/golangci-lint/pull/2438

- 静的単一代入形式のジェネリクス対応issue

https://github.com/golang/go/issues/48525

# おわりに

Go1.18リリースから1週間足らず対応されていて、開発者の方々には本当に頭が上がりません。
これでジェネリクスを使わない理由が無くなったので、どんどん活用していこうと思います！