【发布时间】:2018-09-10 12:17:04
【问题描述】:
这是要重现的代码:
package main
import "fmt"
func main() {
var v []int
v = append(v,1)
v = append(v,v[1:]...)
fmt.Println("hi", v)
}
v[1] 会报告index out of range,但v[1:]... 不会,为什么?
【问题讨论】:
这是要重现的代码:
package main
import "fmt"
func main() {
var v []int
v = append(v,1)
v = append(v,v[1:]...)
fmt.Println("hi", v)
}
v[1] 会报告index out of range,但v[1:]... 不会,为什么?
【问题讨论】:
这就是规范定义切片表达式的方式
对于数组或字符串,如果 0
https://golang.org/ref/spec#Slice_expressions
这就是切片索引表达式的定义方式
如果 0
如果 x 在运行时超出范围,则会发生运行时恐慌
https://golang.org/ref/spec#Index_expressions
你的例子:
v[1] 恐慌,因为根据上面的定义它是我们的范围(因为1 不符合0 <= x < len(a) 的要求)
v[1:] 运行良好,因为它与v[1:len(v)] 相同并且符合if 0 <= low <= high <= cap(a) 的要求。
【讨论】:
v[1] 和 v[1:]... 对于同一切片的行为不同
v[1:] 和v[1:]... 是相同的
v[1] 和 v[1:]...,这是一个错字,抱歉
v[1:] 返回一个列表类型。这里返回一个空列表,因为指定的切片范围内没有任何内容。因此不会引发错误。
v[1] 正在尝试显式地越界访问元素。没有返回默认值,因此会引发错误。
【讨论】:
您可以在最后一个元素之后引用一个空切片,因为这在实现时很有用。
例如。
s := make([]byte, n)
// Fill s with something...
for len(s) > 0 {
b := s[0] // Get next byte
s = s[1:] // Remove it from the slice
// Deal with byte
}
...如果 s[1:1] 不适用于 1 字节切片,则最后一次删除将无效。
【讨论】: