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
您可以在此处阅读有关 arrays、slices 和 maps 的信息:https://blog.golang.org/go-slices-usage-and-internals
先说明一下:
result := make([]string, 0, 4)
make 内置函数分配并初始化类型为 []string
的对象,调用它 Slice
of string
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 = 0
和 capacity = 4
.
而result := make([]string, 4, 4)
分配并初始化了一个[]string
类型的对象length = 4
和capacity = 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
}
我很难学习如何在 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
您可以在此处阅读有关 arrays、slices 和 maps 的信息:https://blog.golang.org/go-slices-usage-and-internals
先说明一下:
result := make([]string, 0, 4)
make 内置函数分配并初始化类型为 []string
的对象,调用它 Slice
of string
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 = 0
和 capacity = 4
.
而result := make([]string, 4, 4)
分配并初始化了一个[]string
类型的对象length = 4
和capacity = 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
}