Block Rockin’ Codes

back with another one of those block rockin' codes

Golang Error Handling lesson by Rob Pike


この記事は Go Advent Calendar 2014 の 15 日目の記事です。


There are many codes like this, while writing a Network Frame Parser program.

var type uint8
err = binary.Read(r, binary.BigEndian, &type)
if err != nil {
    return err

var length uint32
err = binary.Read(r, binary.BigEndian, &length)
if err != nil {
    return err



each function reads length of value from socket and return error if failed.


same things happens in writing to socket code.

さすがにこれが何個も続くと DRY ではないし、エラーの処理を忘れても気づきにくいという問題がある。

same code appears again and again, it's not DRY. and also you probably forget handle error which you can't notice easily.

Go のエラーの問題点

Go では多値を返して、その最後がエラーになるという形式が、一般的でありかつ型として定義されている。

It's a basic way in go, returning multiple values from function, and error is last value of then.


but even if you don't care about return values, it's not compile error.


it means that compiler allows code like this.

// ignore return values
binary.Read(r, binary.BigEndian, &type)
binary.Read(r, binary.BigEndian, &length)


there is no notification when you forgot to process returned value even if it inclueds error.


if you want to fined uncaught error, you need another linter tool.

しかし、例えば戻り値の取得を必須にするとそれもまた問題で、例えば fmt.Println が多値を返すのでプリントデバッグが大変なことになる。

should compiler force programer to handle returned value ? I don't think so, for example fmt.Println returns error too. so its make difficult doing PRINT DEBUG.

_, _ := fmt.Println("print debug")

_, _ := fmt.Println("here")

_, _ := fmt.Println("")

How to solve?

特に Read や Write での処理が増えて行った場合、コードをすっきりさせつつ、 Error を確実に処理する方法について、自分の中では色々と試行錯誤していた。

I tried some practice for make lots of Read/Write proces simple, and make sure process all Errors.

で、先日 のために来日して下さった、 Rob Pike 先生に、この件を聞いてみた。

And I had a chance to ask Mr.Rob Pike about this problem at after party of in Japan last month.

そして Rob 先生は、俺のキーボード(悲しいことに vim しか入ってなかった。。)で、実際に書きながら説明してくれました!!なんという幸運。

and then, Mr.Rob taught me with writting a code on my Mac(unfortunately, I installed only vim...), what's a presious happenig !!


Mr.Rob show me the code like this.

type errWriter struct {
    w io.Writer
    err error

func (e *errWriter) Write(p []byte) {
    if e.err != nil {
    _, e.err = e.w.Write(p)

func (e *errWriter) Err() error {
    return e.err

func do() {
    ew := &errWriter{
        w: ...
    if ew.Err() != nil {
        return ew.Err()
    return nil

Writer の Wrapper になっていて、エラーが発生した時は内部でそれを保持しつつ、以降の処理は全てパスされる。

Write a wrapper struct of Writer. while processing, hold a error if happened and pass all Write() below.


end of the function, check and process the error in struct. this gathers error handling in one place.

とりあえず Writer と Reader について作っておけば、 Write や Read の処理が多くなるほどメリットが大きくなる。

prepare a struct for Writer and Reader has a merit when you write a lot of Write()/Read() process.

素朴だけど Go らしいコードですね。

so simple but powerful as golang way :)



Sorry for hard to watch, but it's more important to see and hear Mr Robs Exmplain haha. be patient :)

Mr. Rob Rike taught me about practice of error handling in Go at GoCon 2014 from Jxck on Vimeo.

Special Thanks

thanks Mr.Rob Pike !

from your student Jxck :)