Go “panic: runtime error: index out of range” when the length of array is not null

Go “panic: runtime error: index out of range” when the length of array is not null

我很难学习如何在 Go 中循环遍历字符串来做一些事情(具体来说,分隔单词而不是包含元音)。

我写了这段代码:https://play.golang.org/p/zgDtOyq6qf

这是我在 运行 时遇到的错误:

panic: runtime error: index out of range

goroutine 1 [running]:
panic(0x1045a0, 0x1040a010)
    /usr/local/go/src/runtime/panic.go:500 +0x720
main.myFunc(0x114130, 0x4, 0x0, 0x0, 0x0, 0x3ba3)
    /tmp/sandbox960520145/main.go:19 +0x1a0
main.main()
    /tmp/sandbox960520145/main.go:10 +0x40

我在论坛里搜了一下,有人说是数组长度的问题,这里不是。我不知道如何解决这个问题。 有人可以提出建议吗?

出现索引超出范围错误,因为您没有初始化足够长度的 result 数组。

myFunc中,您有:

result := make([]string, 0, 4)

这将创建一个字符串切片,它具有长度为 4 的底层数组,但由于您已将切片长度声明为 0,因此切片可以访问底层数组中的 none 元素。所以即使 result[0] 也超出了可用索引的范围。

要解决此问题,只需向 make 提供足够大的长度参数即可:

result := make([]string, 4, 4)

您可以阅读有关切片如何运作的更多信息here

问题是您正在创建一个长度为 0、但最大容量为 4 的切片,但同时您正在尝试将一个值分配给第 0 个创建的切片的索引,通常为空。这就是您收到 index out of range error.

的原因
result := make([]string, 0, 4)
fmt.Println(len(result)) //panic: runtime error: index out of range

您可以更改此代码:

result := make([]string, 4)

这意味着容量将与切片长度相同。

fmt.Println(cap(result)) // 4
fmt.Println(len(result)) // 4

您可以在此处阅读有关 arraysslicesmaps 的信息:https://blog.golang.org/go-slices-usage-and-internals

先说明一下:

result := make([]string, 0, 4)

make 内置函数分配并初始化类型为 []string 的对象,调用它 Slice of string

Slice internals:

A slice is a descriptor of an array segment. It consists of a pointer to the array, the length of the segment, and its capacity (the maximum length of the segment).

因此 result := make([]string, 0, 4) 分配并初始化类型为 []string 的对象 length = 0capacity = 4.
result := make([]string, 4, 4)分配并初始化了一个[]string类型的对象length = 4capacity = 4,等于result := make([]string, 4).

现在result := make([]string, 0, 4)result := make([]string, 4)有什么区别:

使用 result := make([]string, 0, 4) 时,此 Slice 的底层数组为空,这意味着使用 result[0] 会出现恐慌:运行时错误:索引超出范围。

With result := make([]string, 4) 这个 Slice 的底层数组有 4 string 个元素,意思是使用 result[0], result[1], result[2], result[3] 可以:

package main

import "fmt"

func main() {
    result := make([]string, 4)
    fmt.Printf("%q, %q, %q, %q \n", result[0], result[1], result[2], result[3])
}

输出:

"", "", "", "" 

result := make([]string, 4)等于result := []string{"", "", "", ""}意思是这段代码:

package main

import "fmt"

func main() {
    result := []string{"", "", "", ""}
    fmt.Printf("%q, %q, %q, %q \n", result[0], result[1], result[2], result[3])
}

输出与上面的代码相同:

"", "", "", "" 

The append built-in function appends elements to the end of a slice. If it has sufficient capacity, the destination is resliced to accommodate the new elements. If it does not, a new underlying array will be allocated. Append returns the updated slice. It is therefore necessary to store the result of append, often in the variable holding the slice itself:

slice = append(slice, elem1, elem2)
slice = append(slice, anotherSlice...)

As a special case, it is legal to append a string to a byte slice, like this:

slice = append([]byte("hello "), "world"...)

现在在 result := make([]string, 0, 4) 之后的函数 myFunc 内的代码中,您可以使用 append,就像这个工作代码 (The Go Playground):

package main

import (
    "fmt"
    "strings"
)

func main() {
    strs := strings.Fields("Political srt")
    fmt.Println(len(strs)) // It's not empty so why index out of range
    fmt.Println(strs, strs[0], strs[1])
    fmt.Println(strings.ContainsAny(strs[0], "eaiuo"))
    fmt.Println(myFunc("Political srt"))
}

func myFunc(input string) []string {
    strs := strings.Fields(input)
    result := make([]string, 0, 4)
    for i := 0; i < len(strs); i++ {
        if strings.ContainsAny(strs[i], "eaiu") {
            result = append(result, strs[i])
        } else {
            result = append(result, strs[i])
        }
    }
    return result
}

您可以简化该代码,例如这个工作代码 (The Go Playground):

package main

import (
    "fmt"
    "strings"
)

func main() {
    fmt.Println(myFunc("Political srt"))
}

func myFunc(input string) []string {
    strs := strings.Fields(input)
    result := make([]string, 0, 4)
    for _, s := range strs {
        if strings.ContainsAny(s, "eaiu") {
            result = append(result, s)
        }
    }
    return result
}