yyh-gl's icon

yyh-gl's Tech Blog

技術ネタ中心のブログです。主な扱いはバックエンド技術と設計です。

【Go】errorの同値性と表示について調べた

errorに関するちょっとしたメモ

yyh-gl

1 分で読めます

featured

errorについて疑問があった

Goのコードを書いてて、ふと気になったことがあったので調べてみました。

errorの同値性

1つ目の疑問は、下記コードで e1 と e2 がイコールではないことです。
(同値性なんて仰々しく言ってすみません。たったこれだけの疑問です😇🙇‍♂️)

func main() {
	e1 := errors.New("error1")
	e2 := errors.New("error1")
	e3 := e1

	fmt.Println(e1 == e2) // false
	fmt.Println(e1 == e3) // true
}

Playground

結論(errorの同値性)

errors.New() が返しているのがポインタでした。

つまり、さきほどのコードの6行目はポインタの値を比較しているので、そりゃfalseになりますね。

errorの表示

2つ目の疑問は、下記コードで e1 を表示すると、
errors.New()の戻り値である構造体の値ではなく、エラー文言が表示されることです。

package main                                                                                         

import (
	"fmt"
	"errors"
)                                                                                      

func main() {
	e1 := errors.New("error1")

	fmt.Println(e1) // error1
}

Playground

errors.New()が返しているのは構造体なので、
下記コードのように構造体の内容が表示されないのはなんでだ?ってなったわけです。

package main

import "fmt"

func Hoge() interface{} {
	type hoge struct {
		s string
	}
	return &hoge{s: "hoge"}
}

func main() {
	h := Hoge()

	fmt.Println(h) // &{hoge}
}

Playground


まぁ、だいたい予想はついています。
errorってGoの中に組み込まれているやつなので、特別な処理が入っているんでしょう(参考
問題はその処理がどこにあるのかってことですね。


ってことで、該当箇所を探します。




ありました。
ここ ですね。

p.fmtString(v.Error(), verb)

Error() で取り出した値を表示しているようですね。

ということは、、、

package main

import (
	"fmt"
)

type CustomError struct {
	s string
}

func (e CustomError) Error() string {
	return e.s + " この文章が表示されるはず"
}

func NewCustomError(s string) error {
	return &CustomError{s: s}
}

func main() {
	ce1 := NewCustomError("custom error 1")
	fmt.Println(ce1) // custom error 1 この文章が表示されるはず
}

Playground

たしかに、Error() 関数に変更を入れると、表示される内容も変わりましたね。

結論(errorの表示)

errorに関しては、特別な処理が入っていて、Error()で取得した文字列を表示している。

最近の投稿

About

東京で働くソフトウェアエンジニアです。バックエンドがメインですが、フロントエンドやインフラもさわっています。