根据Tour of Go,在Go切片s
中,表达式s[lo:hi]
会计算从lo
到hi-1
的元素切片,包括:
package main
import "fmt"
func main() {
p := []int{0, // slice position 0
10, // slice position 1
20, // slice position 2
30, // slice position 3
40, // slice position 4
50} // slice position 5
fmt.Println(p[0:3]) // => [0 10 20]
}
在我上面的代码示例中," p [0:3]"看起来很直观"阅读" as:"从位置0到位置3和#34;的切片,等于[0,10,20,30]。但当然,它实际上相当于[0 10 20]。
所以我的问题是:评估为hi-1
而不是简单hi
的上限值的设计原理是什么?感觉不直观,但我必须有一些理由让我失踪,我很好奇这可能是什么。
提前致谢。
答案 0 :(得分:10)
这完全是一个惯例问题,当然还有其他方法(例如,Matlab使用第一个索引为1的数组)。选择真正归结为您想要的属性。事实证明,使用0索引数组,其中切片是包容性的(即,从a到b的切片包括元素a并且排除元素b)具有一些非常好的属性,因此它是一种非常常见的选择。以下是一些优点。
0索引数组和包容性排他切片的优点
(注意我使用的是非Go术语,所以我将以C或Java谈论它们的方式讨论数组。数组是Go调用切片,切片是子数组(即, “从索引1到索引4的切片”))
arr
,arr[0:len(arr)]
本身就是arr
。这在实践中很方便。例如,如果我调用n, _ := r.Read(arr)
(其中n
是读入arr
的字节数),那么我可以arr[:n]
来获取{{1}的切片对应于实际写入arr
的数据。指数不重叠。这意味着,如果我有arr
,arr[0:i]
,arr[i:j]
,arr[j:k]
,则这些切片会完全覆盖arr[k:len(arr)]
本身。您可能不会经常发现自己将数组划分为这样的子切片,但它具有许多相关的优点。例如,请考虑以下代码,以基于非连续整数拆分数组:
arr
(这段代码显然不能很好地处理一些边缘情况,但你明白了)
如果我们尝试使用包容性切片来编写等效函数,那将会更加复杂。
如果有人再想一想,请随时编辑此答案并添加。
答案 1 :(得分:3)
The Go Programming Language Specification
对于字符串,数组,指向数组的指针或切片a,主要的 表达
a[low : high]
构造子字符串或切片。指数低和高选择哪个 操作数a的元素出现在结果中。结果有指数 从
0
开始,长度等于high - low
。为方便起见,可省略任何索引。失踪低 index默认为零;缺少的高索引默认为长度 切片的操作数
对于数组或字符串,如果0 <=低&lt; = high&lt; =,则索引在范围内 len(a),否则他们超出范围。对于切片,上部索引 bound是切片容量上限(a)而不是长度。一个常数 index必须是非负的,并且可以通过int类型的值表示; 对于数组或常量字符串,常量索引也必须在 范围。如果两个指数都是常数,则它们必须满足低<=高。如果 指数在运行时超出范围,发生运行时恐慌。
对于q := p[m:n]
,q
是p
的一个切片,从索引m
开始,长度为n-m
个元素。