当数组的长度不为空时出现“panic: runtime error: index out of range”

新手上路,请多包涵

我很难学习如何在 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

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

原文由 jiji 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.4k
2 个回答

问题是您正在创建长度为 0 的切片,但最大容量为 4 ,但同时您正在尝试为第零索引分配一个值创建的切片,通常为空。这就是您收到 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

您可以在此处阅读有关 _数组_、 切片映射 的信息: https ://blog.golang.org/go-slices-usage-and-internals

原文由 Endre Simo 发布,翻译遵循 CC BY-SA 3.0 许可协议

首先解释一下:

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

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

切片内部

切片是数组段的描述符。它由指向数组的指针、段的长度及其容量(段的最大长度)组成。

So result := make([]string, 0, 4) allocates and initializes an object of type []string with length = 0 and capacity = 4 .

And result := make([]string, 4, 4) allocates and initializes an object of type []string with length = 4 and capacity = 4 , which is equal to result := make([]string, 4) .

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

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

With result := make([]string, 4) the underlying array of this Slice has 4 string elements, meaning using 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])
}

输出与上面的代码相同:

 "", "", "", ""


append 内置函数将元素追加到切片的末尾。如果它有足够的容量,则重新切片目的地以容纳新元素。如果没有,将分配一个新的底层数组。 Append 返回更新后的切片。因此有必要存储追加的结果,通常在保存切片本身的变量中:

>  slice = append(slice, elem1, elem2)
> slice = append(slice, anotherSlice...)
>
> ```
>
> 作为一种特殊情况,将字符串附加到字节切片是合法的,如下所示:
>
> ```
>  slice = append([]byte("hello "), "world"...)
>
> ```

* * *

现在在你的代码内部函数 `myFunc` 之后 `result := make([]string, 0, 4)` ,你可以使用 `append` ,就像这个工作代码一样:( [The Go Playground](https://play.golang.org/p/kNb_X1hp5D) ):

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](https://play.golang.org/p/4ZadHTuVZF) ):

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 }

”`

原文由 user6169399 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题