This commit is contained in:
Xargin 2016-12-09 17:43:40 +08:00
parent 1404ebde17
commit 39f43618f6
2 changed files with 3 additions and 3 deletions

View File

@ -44,7 +44,7 @@ endlessSummer := summer[:5] // extend a slice (within capacity)
fmt.Println(endlessSummer) // "[June July August September October]"
```
另外,字符串的切片操作和[]byte字节类型切片的切片操作是类似的。它们都写作x[m:n],并且都是返回一个原始字节系列的子序列,底层都是共享之前的底层数组,因此切片操作对应常量时间复杂度。x[m:n]切片操作对于字符串则生成一个新字符串如果x是[]byte的话则生成一个新的[]byte。
另外,字符串的切片操作和[]byte字节类型切片的切片操作是类似的。都写作x[m:n],并且都是返回一个原始字节系列的子序列,底层都是共享之前的底层数组,因此这种操作都是常量时间复杂度。x[m:n]切片操作对于字符串则生成一个新字符串如果x是[]byte的话则生成一个新的[]byte。
因为slice值包含指向第一个slice元素的指针因此向函数传递slice将允许在函数内部修改底层数组的元素。换句话说复制一个slice只是对底层的数组创建了一个新的slice别名§2.3.2。下面的reverse函数在原内存空间将[]int类型的slice反转而且它可以用于任意长度的slice。
@ -97,7 +97,7 @@ func equal(x, y []string) bool {
上面关于两个slice的深度相等测试运行的时间并不比支持==操作的数组或字符串更多但是为何slice不直接支持比较运算符呢这方面有两个原因。第一个原因一个slice的元素是间接引用的一个slice甚至可以包含自身。虽然有很多办法处理这种情形但是没有一个是简单有效的。
第二个原因因为slice的元素是间接引用的一个固定值的slice在不同的时间可能包含不同的元素因为底层数组的元素可能会被修改。并且Go语言中map等哈希表之类的数据结构的key只做简单的浅拷贝它要求在整个声明周期中相等的key必须对相同的元素。对于像指针或chan之类的引用类型==相等测试可以判断两个是否是引用相同的对象。一个针对slice的浅相等测试的==操作符可能是有一定用处的也能临时解决map类型的key问题但是slice和数组不同的相等测试行为会让人困惑。因此安全的做法是直接禁止slice之间的比较操作。
第二个原因因为slice的元素是间接引用的一个固定的slice值(译注指slice本身的值不是元素的值)在不同的时刻可能包含不同的元素因为底层数组的元素可能会被修改。而例如Go语言中map的key只做简单的浅拷贝它要求key在整个生命周期内保持不变性(译注例如slice扩容就会导致其本身的值/地址变化)。而用深度相等判断的话显然在map的key这种场合不合适。对于像指针或chan之类的引用类型==相等测试可以判断两个是否是引用相同的对象。一个针对slice的浅相等测试的==操作符可能是有一定用处的也能临时解决map类型的key问题但是slice和数组不同的相等测试行为会让人困惑。因此安全的做法是直接禁止slice之间的比较操作。
slice唯一合法的比较操作是和nil比较例如

View File

@ -146,7 +146,7 @@ func equal(x, y map[string]int) bool {
}
```
要注意我们是如何用!ok来区分元素缺失和元素不同的。我们不能简单地用xv != y[k]判断那样会导致在判断下面两个map时产生错误的结果
从例子中可以看到如何用!ok来区分元素不存在与元素存在但为0的。我们不能简单地用xv != y[k]判断那样会导致在判断下面两个map时产生错误的结果
```Go
// True if equal is written incorrectly.