golang 中 array 和 slice 互相转化

2020-07-08 15:33:23 +08:00
 accidentaly

如标题所描述对一下两者进行相互的装换,在不使用 copy 的情况下:

var array [1024]byte

var slice []byte

3338 次点击
所在节点    问与答
12 条回复
accidentaly
2020-07-08 15:53:15 +08:00
如: array ---> slice :
slice:=array[:]

那 slice-->array?
rrfeng
2020-07-08 15:54:19 +08:00
不用 copy 是为啥
accidentaly
2020-07-08 16:14:58 +08:00
因为 copy 实际上是比较慢的
blackeeper
2020-07-08 16:15:30 +08:00
@accidentaly slice-->array [...]array := slice[:]
accidentaly
2020-07-08 16:22:11 +08:00
你这样写是错的把
maoxs2
2020-07-08 16:26:12 +08:00
好像转回来必须 copy,因为 slice 地址不一定是连续的
maoxs2
2020-07-08 16:28:30 +08:00
copy 好像不算慢吧? append 这种在需要 alloc 时候才会比较慢
accidentaly
2020-07-08 16:57:46 +08:00
挺慢的,我测试过了,要求性能高的最好不要 copy
accidentaly
2020-07-08 16:58:37 +08:00
slice 有一部分空间是没在被使用的 冗余空间,如果吧 slice 直接给转换成 array, 那部分冗余就可能会变成内存泄漏了,因为可能没有变量在持有他,所以 golang 不允许反过来的转换, unsafe 转化也是可以的 但是这样会造成泄漏 那就得不偿失了
kiwi95
2020-07-08 17:02:46 +08:00
@maoxs2 slice 底层就是数组,怎么能不是连续的,slice 转最快的是定义一个和 slice 相同的 struct,然后指针转换,但可能存在越界之类的问题
kiwi95
2020-07-08 17:04:40 +08:00
@kiwi95
```go
func TestSlice(t *testing.T) {
var s1 = []int{1, 2, 3, 4, 5}
var s2 [3]int
type slice struct {
Arr unsafe.Pointer
len int
cap int
}
ss := *(*slice)(unsafe.Pointer(&s1))
s2 = *(*[3]int)(ss.Arr)
fmt.Println("s2: ", s2)
}
```
maoxs2
2020-07-08 17:17:49 +08:00
嗯是我搞错了。reflect 里那个 SliceHeader 就是你这个 struct 了,但是这样用得用 keepalive 保留原 array 不然会被 gc

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/688248

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX