【Go】enumっぽいやつのString()メソッド内でpanicを起こした場合、fmtでprintしようとしても握りつぶされる
String()メソッドというか、fmtでprintする時のフォーマットエラーの話
どういうこと
こういう感じ
enumっぽいことをしようとした時に引っかかりそうな問題な気がする
※個人的にはそもそもこのenumっぽいのに不満足だけど今回の話とは関係ないのでスルー
package enum type Kind int const ( _ Kind = iota Dog Cat ) func (k Kind) String() string { switch k { case Dog: return "イヌ" case Cat: return "ネコ" } panic("Err") }
enum_string_err/main.go
package main import ( "enum_string_err/enum" "fmt" ) func main() { var animal enum.Kind animal = enum.Dog fmt.Println(animal) // イヌ animal = enum.Cat fmt.Println(animal) // ネコ var animalDefault enum.Kind fmt.Println(animalDefault) // %!v(PANIC=String method: Err) fmt.Println("---") // --- (上のpanicで止まらず出力される!) x := animalDefault.String() // これは普通にエラーで止まる fmt.Println(x) }
ということで以下の箇所がエラーにならない
var animalDefault enum.Kind fmt.Println(animalDefault) // %!v(PANIC=String method: Err)
これは個人的にはなかなか不便な気がするんだけど、 実務のコードではfmtのprintってよりログ出力することが多いからあんまり問題にならない?
本質
この仕様についてはココに書いてあった(panicとかで検索して原文読んで!)
https://golang.org/pkg/fmt/
一応引用
Format errors:
If an invalid argument is given for a verb, such as providing a string to %d, the generated string will contain a description of the problem, as in these examples:
Wrong type or unknown verb: %!verb(type=value) Printf("%d", "hi"): %!d(string=hi) Too many arguments: %!(EXTRA type=value) Printf("hi", "guys"): hi%!(EXTRA string=guys) Too few arguments: %!verb(MISSING) Printf("hi%d"): hi%!d(MISSING) Non-int for width or precision: %!(BADWIDTH) or %!(BADPREC) Printf("%*s", 4.5, "hi"): %!(BADWIDTH)hi Printf("%.*s", 4.5, "hi"): %!(BADPREC)hi Invalid or invalid use of argument index: %!(BADINDEX) Printf("%*[2]d", 7): %!d(BADINDEX) Printf("%.[2]d", 7): %!d(BADINDEX)
If an Error or String method triggers a panic when called by a print routine, the fmt package reformats the error message from the panic, decorating it with an indication that it came through the fmt package. For example, if a String method calls panic("bad"), the resulting formatted message will look like
%!s(PANIC=bad)
The %!s just shows the print verb in use when the failure occurred. If the panic is caused by a nil receiver to an Error or String method, however, the output is the undecorated string, "\<nil>".
この後半の
If an Error or String method triggers a panic when called by a print routine,
のところで今回の話についてピンポイントで触れている