Go error handling is really confusing me.

polaris · 2017-11-09 17:00:26 · 745 次点击    
这是一个分享于 2017-11-09 17:00:26 的资源,其中的信息可能已经有所发展或是发生改变。

I have a *http.Request, I call .Cookie("session") on it, get back a possible cookie and a possible error. I handle it by just log.Fataling it while I tool around, and I get http: named cookie not present.

Makes sense, that is a perfectly expected error I want to handle. But what's the pattern for doing that? In Ruby, for example, it would throw an exception like CookieNotFound and I would rescue CookieNotFound and then explain what to do in that situation. Do I just need to call the Error() function on the error, get the string, match against the string in a case statement, and copy logic between branches? I'd love some examples of well-handled errors.

As a side question: why is making things nil-able and passing separate possible errors around chosen over union types?


评论:

oscooter:

The http lib news up an instance of each type of error it will return and returns those. You can see here that the Cookie func will return the ErrNoCookie instance in the http package.

So you can check if it's a the cookie not present error by doing

if err == http.ErrNoCookie {
    // handle this specific error
}

The documentation for the http package also shows some of the other errors the package can return.

Note that this can vary by package. The stdlib of go typically uses this method but other packages may expect you to do a type assertion on the error to check which type of error you got back.

Here's a handy article that explains the type assertion method in more depth.

acln0:

The return value of the Error() string method is purely informative and should never be used for flow control.

Errors come in a number of flavors and good libraries document the errors they return.

The first flavor is errors like http.ErrNoCookie, io.EOF or bufio.ErrBufferFull. Such errors are effectively constants and are usually named ErrSomething. You check for them with simple equality:

if err == http.ErrNoCookie {
    // do something
}

Another flavor is like net.OpError, os.PathError, or strconv.NumError, which represent a type of error rather than an exact error. These usually wrap an inner error with additional information. Such error types are usually named SomethingError. You check for such errors using a type assertion, like so:

if perr, ok := err.(*os.PathError); ok { 
    // use concrete information in perr
}

Finally, you have interfaces like net.Error, which are desirable over concretely typed errors, because they reduce potential coupling between packages. Think of the net.Error interface as being a piece of documentation for optional methods the errors returned by package net may have.

If a type which implements error also implements a Timeout() bool method, the caller need not know about the package the error came from or its concrete type. A check like this is sufficient:

type timeouter interface {
    error
    Timeout() bool
}
if terr, ok := err.(timeouter); ok {
    // check terr.Timeout()
}
mxxxz:

is this handling equivalent of try-catch statements in Java?


入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

745 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传