英文:
How to use run time error in golang?
问题
我正在尝试从3个服务器下载文件。我的想法是,如果第一个服务器关闭了,就使用第二个服务器。我注意到,如果第一个服务器关闭了,会出现运行时错误。我想知道如何利用这个错误,我需要像这样的代码:
if run time err!=nil{do something}
我是Go语言的新手,希望有人可以帮助我。谢谢。
英文:
I am trying to download something from 3 servers. My idea is if the first server is closed,it will use the second server. I noticed,if the first server has been closed, it will created a run time error.I want to know how to use this error,what i need is like this:
if run time err!=nil{do something}
i am new to golang,hope someone can help me
thank you
答案1
得分: 9
为了详细说明FUZxxl的解释,Go语言在错误(something which could go wrong indeed went wrong)和异常(something which could not possibly go wrong actually went wrong)之间进行了区分。
这种区分有时可能很微妙(因为它依赖于“意外”),但它也可以比其他语言中的“一切皆异常”更清晰。
例如,考虑可能溢出的整数。一种可能是将其视为“正常”行为,应该适当处理:
func safe_add(x, y uint32) (uint32, error) {
z := x + y
if z < x || z < y {
return 0, fmt.Errorf("Integer overflow")
}
return z, nil
}
另一种可能是将其视为“永远不会发生”的情况,并在发生时通过运行时的panic
处理:
func panic_add(x, y uint32) uint32 {
z, err := safe_add(x, y)
if err != nil {
panic(err)
}
return z
}
(请注意,我在这里使用了自己的safe_add
,但你当然不必这样做)
主要区别在于之后如何处理错误。使用error
将数字相加直到溢出的示例:
func safeloop(u uint32) {
var err error
for {
if u, err = safe_add(u, u); err != nil {
fmt.Println(err)
return
} else {
fmt.Println(u)
}
}
}
而处理panic使用了recover
内置函数:
func panicloop(u uint32) {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}()
for {
u = panic_add(u, u)
fmt.Println(u)
}
}
(完整示例请参见playground)
请注意,panic版本的循环要简单得多,因为你基本上不期望出现任何错误,也不会检查错误。与之相对应的是,处理panic的方式相当繁琐,即使对于像这样非常简单的示例也是如此。你可以使用defer
一个函数来调用recover
并捕获错误,当它出现并中断函数时。当你的代码变得更复杂时,跟踪panic发生的位置/方式并相应地采取措施可能比在可能出现错误的地方检查错误的方式要复杂得多,使用result, err := func_which_may_fail(...)
模式。
你甚至可以在panic、recover返回错误、将错误转换为panic之间进行交替,但这被认为是不良设计。
关于错误处理和panic,有一些很好的资源可以在Go博客上找到。错误处理和panic以及规范都是很好的阅读材料。
在你的情况下,由于你预期“服务器已关闭”是一个相当频繁的行为,你应该像FUZxxl建议的那样使用error
方式,但我希望这对你(或其他人)理解Go中的错误处理方式有所帮助。
英文:
To elaborate on what FUZxxl explained, go makes a distinction between an error (something which could go wrong indeed went wrong) and an exception (something which could not possibly go wrong actually went wrong).
The distinction can sometimes be subtle (as it relies on what is 'unexpected'), but it can also be clearer than the 'everything is an exception' that you see in other languages.
For instance, consider integers which might overflow. One possibility is to consider it a 'normal' behaviour, which should be handled appropriately:
func safe_add(x, y uint32) (uint32, error) {
z := x + y
if z < x || z < y {
return 0, fmt.Errorf("Integer overflow")
}
return z, nil
}
Another is to consider it 'never happens' and have the runtime panic
in the unlikely case when it happens against all odds:
func panic_add(x, y uint32) uint32 {
z, err := safe_add(x, y)
if err != nil {
panic(err)
}
return z
}
(Note that I use my own 'safe_add' here, but you don't have to of course)
The main difference is in the way you handle the error afterwards. Adding a number to itself until it overflows with error
s gives:
func safeloop(u uint32) {
var err error
for {
if u, err = safe_add(u, u); err != nil {
fmt.Println(err)
return
} else {
fmt.Println(u)
}
}
}
While handling panics uses the recover
built-in function:
func panicloop(u uint32) {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}()
for {
u = panic_add(u, u)
fmt.Println(u)
}
}
(full examples on the playground)
Note that the panic version has a much simpler loop, as you basically never expect anything to go wrong and never check for errors. The counterpart for this is that the way to handle panics is quite cumbersome, even for a very simple example like this. You defer
a function which will call recover
and capture the error when it arises and breaks out of the function. When your code becomes more complex, tracking exactly where/how the panic arose and acting on it accordingly can become much more complex than checking for errors in places where they could arise, with the result, err := func_which_may_fail(...)
pattern.
You can even alternate between panics, recover which return errors, errors converted to panics, ... but this is (understandably) considered poor design.
There are some good resources on error handling and panics on the go blog. The specs is a good read to.
In your case, as you expect 'the server is closed' to be a pretty frequent behaviour, you should definitely go the error
way, as FUZxxl suggested, but I hope this might be useful to you (or others) to understand how error handling works in Go.
答案2
得分: 1
当你做一些可能出错的操作时,会得到一个error
对象。
bytes, err = stream.Read(buffer)
为了检查你尝试的操作是否出错,可以将error
对象与nil
进行比较。nil
表示没有发生错误。如果错误不是nil
,你可以对其进行处理。
if err != nil {
// 在这里处理错误
}
英文:
When you do something which could go wrong, you get an error
object.
bytes, err = stream.Read(buffer)
To check whether what you tried actually went wrong, compare the error
object against nil
. nil
signalizes that no error has happened. In the case the error is not nil
, you can do something about it.
if err != nil {
// insert error handling here
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论