Golang Go语言中 slice defaults 这里是坑还是如此设计?
Golang Go语言中 slice defaults 这里是坑还是如此设计?
// https://tour.golang.org/moretypes/10
package main
import "fmt"
func main() { s := []int{1, 2, 3, 4, 5, 6}
s = s[1:4]
fmt.Println(s)
s = s[:5]
fmt.Println(s) // 这里 s 接上面的起点 2,但是终点却是 6 ?
s = s[1:]
fmt.Println(s)
}
////output
[2 3 4]
[2 3 4 5 6]
[3 4 5 6]
更多关于Golang Go语言中 slice defaults 这里是坑还是如此设计?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
下标从 0 开始呀,哪里坑了?
更多关于Golang Go语言中 slice defaults 这里是坑还是如此设计?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这是设计,边界不超过 cap 就行
这种赋值操作一般不推荐吧,你使用的始终是一个对象
下表从零开始,end 的值是末尾元素下标+1。这种用法有梗的
看岔了,忽略
第二个用法我其实挺惊讶的
我一直以为边界是 len 这样看是 cap
是下标结尾哈
直觉上理解,slice 前后边界应该是限定了。
比如第三次 slice 的首边界就在原来基础上+1 了。
如果第二次 slice 能将上一个尾部扩展的话,那么首边界却不能往前移动,这点反直觉吧
是不推荐。反直觉啊
对
数组越界了,所以取到了 slice 外面的东西,这时候是未定义行为,取到任何东西都不奇怪。只是这里 slice 没有发生拷贝,取到了原地址后面的东西了。
至于取分片为什么没有拷贝或者不做越界检查当然是为了性能,所以挺合理的
切片和数组是不同的. 两种类型能够索引数据的范围都是在 len(x)之内的.
但是切片可以通过重新切片来扩展它的 len, 重新切片允许的范围是其底层数组决定的, 它等于切片的 cap.
不存在数组越界和未定义行为这种说法.
嗯,试了下你说的是对的
这么解释不知道合不合适:
// origin
s := []int{1, 2, 3, 4, 5, 6}
s = s[1:4]
// 此时 s 是原数组的切片,其内容就是[2 3 4],索引 index 1, 2, 3 的值
// 但原数组的 cap 比现在的切片大,所以目前是可以扩展的
// [2 3 4]
fmt.Println(s)
s = s[:5]
// 进行重切片,此时发现原切片不够大,但底层数组的 cap 够,也就增加了后面的 6,就是 index=4 的值
fmt.Println(s)
// [2 3 4 5 6]
s = s[1:]
// 此时又重新切片 去掉第一个元素 index=0,也就是 2,那么返回的数据就是[3 4 5 6]
fmt.Println(s)
// [3 4 5 6]
谢谢楼上各位的讨论和回答。总结一下
package main
import (
“fmt”
)
func main() {
fmt.Println(“Hello, playground”)
a := []int{1,2,3,4,5,6}
printSlice(a)
b := a[1:3]
b[0] = 0
printSlice(b)
c := b[:3]
c[0] = 0
printSlice©
//d := c[-1:] 可惜不能往前扩
//printSlice(d)
d := c[1:4]
d[0] = 0
printSlice(d)
e := d[1:4] //通过小切片来移动窗口处理数据还是挺方便的。
e[0]=0
printSlice(e)
printSlice(a)
}
func printSlice(s []int) {
fmt.Printf(“len=%d cap=%d %v\n”, len(s), cap(s), s)
}
Hello, playground
len=6 cap=6 [1 2 3 4 5 6]
len=2 cap=5 [0 3]
len=3 cap=5 [0 3 4]
len=3 cap=4 [0 4 5]
len=3 cap=3 [0 5 6]
len=6 cap=6 [1 0 0 0 5 6]
另外,append 后,变量指向新数组实例了。
在Golang(Go语言)中,slice的默认行为确实可能让初学者感到困惑,但这一设计有其深刻的原因和合理性。
首先,要理解slice是Go语言中的一种动态数组,它是对底层数组的抽象和引用。slice有三个关键组成部分:指向底层数组的指针、slice的长度和slice的容量。
当你创建一个新的slice,如s := []int{}
,这个slice实际上是引用了一个空的底层数组,并且它的长度和容量都为0。这并不是一个“坑”,而是slice设计的一部分,它允许slice在需要时动态地增长和收缩。
当你向slice中添加元素时,如果slice的容量不足以容纳新元素,Go会自动分配一个新的底层数组,并将旧数组的元素复制到新数组中。这个过程是自动且高效的,但也需要开发者理解slice的底层实现,以避免不必要的性能开销。
此外,slice的默认行为也体现了Go语言的设计哲学:简洁、直接和高效。通过减少不必要的初始化步骤,Go使得slice的使用更加灵活和高效。
因此,对于“slice defaults是坑还是如此设计”的问题,答案是:这是Go语言slice的如此设计。它允许开发者以简洁、高效的方式使用动态数组,同时也需要开发者理解其底层实现,以充分利用其性能优势。