LoginSignup
0
0

More than 1 year has passed since last update.

go-cmpでpanicがおきたら

Last updated at Posted at 2021-07-15

対処方法

package main

import (
    "fmt"

    "github.com/google/go-cmp/cmp"
    "github.com/google/go-cmp/cmp/cmpopts"
)

type Struct struct {
    XXX int
    xxx int
}

func main() {
    s1 := Struct{ 1, 1}
    s2 := Struct{ 1, 2}

    opt := cmpopts.IgnoreUnexported(Struct{}) // ここ大事
    fmt.Println("Diff: ", cmp.Diff(s1, s2, opt))
}

PlayGroundで試す

もう少し詳しく

どうやらgo-cmpは、プライベートな変数があるとパニックになってしまうらしい。
実はこのプライベートの取り扱い方でいくつかパターンが用意されている。

プライベート変数は一致しなくてよい場合

import (
    "github.com/google/go-cmp/cmp"
    "github.com/google/go-cmp/cmp/cmpopts"
...
    opt := cmpopts.IgnoreUnexported(Struct{}) // 最初のものと一緒
    fmt.Println("Diff: ", cmp.Diff(s1, s2, opt))

PlayGroundで試す

プライベート変数も一致していてほしい場合

import (
    "github.com/google/go-cmp/cmp"
...
    opt := cmp.AllowUnexported(Struct{}) // こちらはcmpoptsではないので注意
    fmt.Println("Diff: ", cmp.Diff(s1, s2, opt))

PlayGroundで試す

指定した変数のみ無視してほしい場合

import (
    "github.com/google/go-cmp/cmp"
...
    // 変数名を文字列で指定, パブリック変数も指定可能
    opt := cmpopts.IgnoreFields(Struct{}, "xxx") 
    fmt.Println("Diff: ", cmp.Diff(s1, s2, opt))

PlayGroundで試す

さらに詳しく

ここまでで解決できない方は恐らく、構造体が複数の層に分かれているかと思います。
今回は、各構造体のプライベート変数の一致を無視した場合の対処法を以下に示します。
各自のユースケースに合わせてご使用ください。

package main

import (
    "github.com/google/go-cmp/cmp"
    "github.com/google/go-cmp/cmp/cmpopts"
)

var (
    ignoreOpts = cmpopts.IgnoreUnexported(
        Car{},
        Wheel{},
    )
    car1 = &Car {
        speed: 2.0,
        Wheels: []*Wheel{
            &Wheel{
                Size: 3.0,
                hardness: 1.0,
            },
            &Wheel{
                Size: 4.0,
                hardness: 2.0,
            },
            &Wheel{
                Size: 5.0,
                hardness: 3.0,
            },
            &Wheel{
                Size: 6.0,
                hardness: 4.0,
            },
        },
    }
    car2 = &Car {
        speed: 4.0,
        Wheels: []*Wheel{
            &Wheel{
                Size: 3.0,
                hardness: 4.0,
            },
            &Wheel{
                Size: 4.0,
                hardness: 3.0,
            },
            &Wheel{
                Size: 5.0,
                hardness: 2.0,
            },
            &Wheel{
                Size: 6.0,
                hardness: 1.0,
            },
        },
    }
    car3 = &Car {
        speed: 2.0,
        Wheels: []*Wheel{
            &Wheel{
                Size: 3.0,
                hardness: 1.0,
            },
            &Wheel{
                Size: 4.0,
                hardness: 2.0,
            },
            &Wheel{
                Size: 5.0,
                hardness: 3.0,
            },
        },
    }

)

type Car struct {
    speed float64
    Wheels []*Wheel
}

type Wheel struct {
    Size float64
    hardness float64
}

func CarDiff(left *Car, right *Car) string {
    return cmp.Diff(left, right, ignoreOpts)
}

func main() {
    println("car1 & car2\n", CarDiff(car1, car2))
    println("car1 & car3\n", CarDiff(car1, car3))
}

PlayGroundで試す

その他

まとめて比較してくれる機能は大変便利ですが、使用する場合はテストの結果を比較するときか、簡単なコードを書くときくらいにしときましょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0