https://qiita.com/niusounds/items/0f458be1ecce8a955a64

突然ですが問題です。 以下のコードを実行した時、"This should not be called"の文字列は出力されるでしょうか?

package main

import "fmt"

type MyError struct {
}

// implements error interface
func (MyError) Error() string {
    return "This is MyError"
}

func fn() (int, *MyError) {
    return 42, nil
}

func main() {
    result, err := fn()
    if err != nil {
        fmt.Println("This should not be called")
    }
    fmt.Println(result, err)
}

出てません。fn()はエラーnilを返しているので、if err != nilの中には入りません。 ここまではOKですね。

では次の例ではどうでしょうか。

package main

import "fmt"

type MyError struct {
}

// implements error interface
func (MyError) Error() string {
    return "This is MyError"
}

func fn() (int, *MyError) {
    return 42, nil
}

func main() {
    var err error
    result, err := fn()
    if err != nil {
        fmt.Println("This should not be called")
    }
    fmt.Println(result, err)
}

func main()の次の行に1行追加されているだけですが、これはどうなるでしょう?

なんと!"This should not be called"の文字列が出力されてしまいました! ということはerr != niltrueということになります。 でもちょっとまってください。その下の出力内容は42 <nil>です。ということはerrはやっぱりnilなのです。だから、

if err != nil {
  fmt.Printf("Error %s", err.Error())
}

のようなことをしていると、直前でnilチェックをしているにも関わらずnil参照エラーでクラッシュします。

私はこの現象に数時間悩まされました。

この例で言うところのfn()が返却するエラーの型を*MyErrorではなくerrorとすると、この問題は発生しません。

package main

import "fmt"

type MyError struct {
}

// implements error interface
func (MyError) Error() string {
    return "This is MyError"
}

func fn() (int, error) { // *MyErrorではなくerror
    return 42, nil
}

func main() {
    var err error
    result, err := fn()
    if err != nil {
        fmt.Println("This should not be called")
    }
    fmt.Println(result, err)
}

Goの型システムの深いところまでまだ理解できていないのですが、とりあえず各関数が返却するエラーの型を*MyErrorのような独自型ではなく、errorとするのが良さそうです。

同じハマり方をされていた先人たち

Why not register and get more from Qiita?

  1. We will deliver articles that match youBy following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficientlyBy "stocking" the articles you like, you can search right away