wsl_v5

Table of Contents

  1. 解決する問題
  2. 設定
  3. オプション
    1. 基本設定
    2. チェック項目(デフォルトで有効)
    3. チェック項目(デフォルトで無効)
  4. サンプル
    1. 検出例
    2. 修正例
  5. 注意点
  6. 参考リンク

wsl_v5 はコードブロック間の空行の使い方を強制し、可読性を向上させるホワイトスペース Linter です。

解決する問題

異なる種類の文(代入、条件分岐、関数呼び出しなど)が空行なしに密集していると、コードの論理的なグループが読み取りにくくなります。wsl はブロック文の前後に適切な空行を入れることを強制し、一貫したコードスタイルを維持します。

1
2
3
4
5
6
7
8
9
10
11
12
13
// Before: 空行が不適切でグループ分けが不明瞭
func ProcessOrder(ctx context.Context, order Order) error {
total := order.CalcTotal()
if total <= 0 {
return ErrInvalidTotal
}
discount := calcDiscount(order)
total -= discount
if err := validateOrder(order); err != nil {
return err
}
return saveOrder(ctx, order, total)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// After: 論理的なグループを空行で分離
func ProcessOrder(ctx context.Context, order Order) error {
total := order.CalcTotal()

if total <= 0 {
return ErrInvalidTotal
}

discount := calcDiscount(order)
total -= discount

if err := validateOrder(order); err != nil {
return err
}

return saveOrder(ctx, order, total)
}

設定

公式ドキュメント

1
2
3
4
5
6
7
8
9
10
11
12
# .golangci.yml 設定例
version: "2"

linters:
enable:
- wsl_v5
settings:
wsl_v5:
allow-first-in-block: true
allow-whole-block: false
branch-max-lines: 2
case-max-lines: 0

オプション

基本設定

オプション デフォルト 説明
allow-first-in-block bool true ブロック内で最初に使用される変数の隣接を許可する
allow-whole-block bool false ネストされたブロック内のどこかで使用される変数の隣接を許可する
branch-max-lines int 2 分岐文がこの行数以下なら空行なしで隣接を許可
case-max-lines int 0 case ブロックの最大行数(0 は無制限)
include-generated bool false 生成されたファイルもチェック対象にする

チェック項目(デフォルトで有効)

チェック 説明
append append は直前の行で使用された値に対してのみ隣接可
assign 代入文は他の代入文やインクリメント演算子とグループ化
branch 分岐文は branch-max-lines に基づいて空行を要求
decl 宣言文は他の文と隣接しない
defer defer は他の defer またはエラーチェック後にのみ隣接可
err エラーチェックはエラーの代入直後に配置
for / if / range / switch / select ブロック文は直前で使用する変数とのみ隣接可
return returnbranch-max-lines に基づいて空行を要求
leading-whitespace ブロック先頭の空行を除去
trailing-whitespace ブロック末尾の空行を除去

チェック項目(デフォルトで無効)

チェック 説明
after-block ブロックの後に空行を要求
assign-exclusive 新しい変数宣言と再代入を分離
assign-expr 代入と関数呼び出しの混在を防止

サンプル

検出例

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
// wsl_v5 が警告するパターン

// 1. if 文の前に空行がない
func example1(x int) error {
y := x * 2
if y > 100 { // if statements should only be cuddled with assignments used in the if statement
return ErrTooLarge
}

return nil
}

// 2. エラーチェックがエラー代入の直後でない
func example2(ctx context.Context) error {
err := doSomething(ctx)
slog.Info("done")
if err != nil { // if statements that check an error must be cuddled with the statement that assigned the error
return err
}

return nil
}

// 3. ブロック先頭の不要な空行
func example3() {

fmt.Println("hello") // leading whitespace: block should not start with an empty line
}

// 4. 宣言と他の文が隣接
func example4() {
x := 10
var y int // declarations should not be cuddled with other statements
y = x
fmt.Println(y)
}

修正例

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
// 1. if 文の前に空行を追加(y は if で使用していないため)
func example1(x int) error {
y := x * 2

if y > 100 {
return ErrTooLarge
}

return nil
}

// 2. エラーチェックをエラー代入の直後に配置
func example2(ctx context.Context) error {
err := doSomething(ctx)
if err != nil {
return err
}

slog.Info("done")

return nil
}

// 3. ブロック先頭の空行を除去
func example3() {
fmt.Println("hello")
}

// 4. 宣言の前に空行を追加
func example4() {
x := 10

var y int

y = x
fmt.Println(y)
}

注意点

  • golangci-lint では旧バージョンの wsl と区別するため wsl_v5 として登録されている。旧 wsl は非推奨
  • v5 ではチェック項目を個別にオン・オフできるようになった。チームのスタイルに合わせてカスタマイズ可能
  • allow-first-in-block: true(デフォルト)では、ブロック内の直後に使用される変数のみ隣接が許可される
  • エラーチェック(err チェック)は代入の直後に配置するルールが強制される。これは Go の慣習的なエラーハンドリングパターンに合致する
  • golangci-lint-migrate コマンドで旧 wsl 設定を v5 形式に変換できる

参考リンク