panic: runtime error: index out of range

首先先看一个示例,看看你能否发现代码中的问题。

package main

import "fmt"

func main() {
    arr := []string{"hello", "world"}
    fmt.Println(test(arr))
}

func test(arr []string) string {
    return arr[0]
}

在实际工作中,可能不会写这么简单的代码,但是上面代码的错误在你的代码中有可能会出现。至于上面代码错在哪里,其原因在于当引用一个为nil的切片时,即使下标为0的元素,也会造成代码出现index out of range

package main

import "fmt"

func main() {
    arr := []string{"hello", "world"}
    fmt.Println(test(arr))
    fmt.Println(test(nil))
}

func test(arr []string) string {
    return arr[0]
}

执行上述代码,就会触发panic,导致程序不能继续运行。在多层嵌套的函数调用中出现panic,程序会马上中止当前函数的执行,所有的defer语句会把控制权交还给接收到panic的函数调用者。这样向上冒泡直到最顶层,并执行每层的defer,然后在栈顶处程序崩溃。

hello
panic: runtime error: index out of range

goroutine 1 [running]:
main.test(...)
        D:/mygo/test.go:12
main.main()
        D:/mygo/test.go:7 +0xc0
exit status 2

在实际应用中,这一情况是不允许出现的,即使出现panic,也不能让程序停止运行。可以的做法就是使用recover内建函数,让程序从panic中恢复。其中recover只能在defer修饰的函数中使用,用于取得panic调用中传递过来的错误值,如果是正常执行,调用recover会返回nil,且没有其他效果。

package main

import "fmt"

func main() {
    arr1 := []string{"hello", "world"}
    fmt.Println(test(arr1))
    defer func() {
        if err := recover(); err != nil {
            fmt.Printf("panic %s\n", err)
        }
    }()
    fmt.Println(test(nil))
}

func test(arr []string) string {
    return arr[0]
}

还有另外一种方法,就是在含有切片参数的函数中,首先对参数进行判断。例如:

package main

import "fmt"

func main() {
    arr := []string{"hello", "world"}
    fmt.Println(test(arr))
    fmt.Println(test(nil))
}

func test(arr []string) string {
    if len(arr) != 0 {
        return arr[0]
    }else {
        return "error" 
    }
}

猜你喜欢

转载自blog.csdn.net/benben_2015/article/details/81020296