我很难学习如何在Golang
中循环一个字符串来做一些事情(单词而不是包含元音)。
我写了这段代码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
我在这个论坛上搜索过,有人说这是由于阵列的长度,但事实并非如此。我无法弄清楚如何解决这个问题。 有人可以建议吗?感谢
答案 0 :(得分:2)
首先让我们解释一下:
result := make([]string, 0, 4)
make内置函数分配并初始化[]string
类型的对象,将其Slice
称为string
切片是数组段的描述符。它由一个指针组成 到数组,段的长度,以及它的容量(最大值 段的长度)。
所以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]
将会出现紧急情况:运行时错误:索引超出范围。
使用result := make([]string, 4)
此Slice的基础数组有4个string
个元素,这意味着使用result[0]
,result[1]
,result[2]
,result[3]
是OK:
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内置函数 将元素附加到切片的末尾。如果它有足够的容量, 目的地被重新分配以容纳新元素。如果它 不会,将分配一个新的底层数组。追加返回 更新切片。因此有必要存储结果 追加,通常在持有切片本身的变量中:
slice = append(slice, elem1, elem2) slice = append(slice, anotherSlice...)
作为一种特殊情况,将字符串附加到字节切片是合法的, 像这样:
slice = append([]byte("hello "), "world"...)
现在在myFunc
之后的函数result := make([]string, 0, 4)
内的代码中,您可以使用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
}
答案 1 :(得分:1)
问题是您正在创建一个长度为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
您可以在此处阅读数组,切片和地图:https://blog.golang.org/go-slices-usage-and-internals
答案 2 :(得分:0)
索引超出范围错误正在出现,因为您没有以足够的长度初始化result
数组。
在myFunc
中,您有:
result := make([]string, 0, 4)
这将创建一个字符串切片,其中包含一个长度为4的基础数组,但由于您已将切片长度声明为0,因此切片无法访问基础数组中的任何元素。所以即使result[0]
超出了可用指数的范围。
要解决此问题,只需向make
提供足够大的长度参数:
result := make([]string, 4, 4)
您可以详细了解切片如何操作here。