如何在Golang中使用运行时错误?

问题描述:

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

我正在尝试从3台服务器下载某些内容。 我的想法是,如果第一台服务器关闭,它将使用第二台服务器。 我注意到,如果第一台服务器已经关闭,它将创建一个运行时错误。我想知道如何使用此错误,我需要的是这样的: p>

  如果运行时错误!= nil {做某事} 
  code>  pre> 
 
 

我是golang的新手,希望有人可以帮助我 谢谢 p> DIV>

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 errors 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.

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
}