tour of go で学んだ Error() の定義と呼び方

問題 https://go-tour-jp.appspot.com/methods/20

検証コード Go Playground - The Go Programming Language

Error() の実行

Error() を実行させるためには、 error インタフェースを満たす値を fmt の print系の関数に渡してやる。
print系関数の中身では、渡された引数の error をチェックして not nil なら Error() を実行するような動きになるため。

// func ReturnErrFn() error {}
fmt.Println(ReturnErrFn())

「error インタフェースを満たす値」とは、Error() メソッドを呼び出せる型のこと。

func (e ErrNegativeSqrt) Error() string {
    return fmt.Sprintf("Err: ErrNegativeSqrt: %v", float64(e))
}

つまり、ある変数がこのメソッドを呼び出せるなら、その変数は error インタフェースを満たしている。(error インタフェースは Error() メソッドのみを実装しているため)
よってその変数を fmt の print系に渡せば、通常のprintではなく Error() が実行される。

Error() メソッドのレシーバは変数かポインタか?

ポインタレシーバにすると、呼び出し元の変数はポインタでなければならない。

func (e *ErrNegativeSqrt) Error() string {
    return fmt.Sprintf("Err: ErrNegativeSqrt: %v", float64(e))
}

// ok
fmt.Println(RetErr(&errNegativeSqrt))

// fail
fmt.Println(RetErr(errNegativeSqrt))

対して変数レシーバの場合、呼び出し元は変数でもポインタでもどちらでもよい。

func (e ErrNegativeSqrt) Error() string {
    return fmt.Sprintf("Err: ErrNegativeSqrt: %v", float64(e))
}

// ok
fmt.Println(RetErr(&errNegativeSqrt))

// ok
fmt.Println(RetErr(errNegativeSqrt))

有効な error インタフェース値の返却方法?

なんからの関数で error を返却する場合、エラーとなる書き方がある。

type ErrNegativeSqrt float64
func RetErr(x float64) error {
    // fail
    return &ErrNegativeSqrt(x)

    // fail
    var errNegativeSqrt *ErrNegativeSqrt = &(ErrNegativeSqrt(x))
    return errNegativeSqrt

    // ok
    var errNegativeSqrt ErrNegativeSqrt = ErrNegativeSqrt(x)
    return &errNegativeSqrt

    // ok (error == nil なのでこれを print しても Error() は実行されない)
    var errNegativeSqrt *ErrNegativeSqrt
    return errNegativeSqrt
}

一旦現在のスコープの変数にコピーしてからそのアドレスを返却する必要がありそう。
実行結果(右辺)のアドレスはその行が終了した時点でdropされて dangling pointer のようになっているのだろうか。。