Tag Archives: GO Learning Summary

panic: runtime error: index out of range

Let’s start with an example to see if you can spot problems in the code.

package main

import "fmt"

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

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

In real life, you probably wouldn’t write this simple code, but the errors in the above code might occur in your code. As for what is wrong with the above code, the reason is that when referring to a slice that is nil, even the element with the index of 0 will cause the code to appear 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]
}

Execute the above code, and a panic will be triggered, causing the program to stop running. When panic occurs in a multi-layered nested function call, the program immediately aborts the execution of the current function, and all defer statements return control to the caller who received the panic. This bubbles up to the top layer, executes defer for each layer, and then crashes the program at the top of the stack.

hello
panic: runtime error: index out of range

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

In a practical application, this situation is not allowed, and there is no panic to stop the program. You can do this by using the recover built-in function to recover the program from panic. Where recover can only be used in the defer decorated function to get the error value passed in the panic call, if it is executed normally, the call recover returns nil and has no other effect.

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]
}

Another method is to first judge the parameters in the function containing the slice parameters. Such as:

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" 
    }
}