Go语言模型:切片slice的底层实现

Go语言的切片实现可以看runtime的slice.go文件,切片是Go语言内置的数据结构,编译器识别到切片语法操作时会自动调用runtime对应底层实现,所以用起来就非常方便,这也是语言级的实现比库实现的优势。
可以通过一个例子来看切片的内存模型:

// go version: 1.7
package main

import (
    "fmt"
    "reflect"
    "unsafe"
)

// GDB时,避免局部变量可能会被优化,全局变量方便GDB查看进程对应内存
// 编译时加调试信息并去掉优化: go build -gcflags "-N -l" hi.go
var (
    a = [...]int{1, 2, 3, 4, 5} // 数组
    b = a[2:4]                  // 切片 --> 通过数组+[:]语法生成切片
    c = &a                      // 指针指向数组
    d = []int{1, 2, 3}          // 切片 --> 直接初始化切片[]Type{data..}语法
)

// runtime: 拷贝自slice.go的私有结构体, 64位操作系统就是24个字节大小
type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}

func main() {
    fmt.Println("&a[2]", &a[2])                        // &a[2] 0xf8270
    fmt.Println("len", len(b), "cap", cap(b))          // len 2 cap 3
    fmt.Println(reflect.TypeOf(a), unsafe.Sizeof(a))   // [5]int 40
    fmt.Println(reflect.TypeOf(b), unsafe.Sizeof(b))   // []int 24
    fmt.Println(reflect.TypeOf(c), unsafe.Sizeof(c))   // *[5]int 8
    fmt.Printf("%+v\n", *(*slice)(unsafe.Pointer(&b))) // {array:0xf8270 len:2 cap:3}
    fmt.Printf("%+v\n", *(*slice)(unsafe.Pointer(&d))) // {array:0xf8090 len:3 cap:3}

    // append 出发自动扩容,生成一个新的切片实例
    fmt.Println(unsafe.Pointer(&d)) // 0xfa100
    d = append(d, 4)
    fmt.Printf("%+v\n", *(*slice)(unsafe.Pointer(&d))) // {array:0xc4200121e0 len:4 cap:6}
    fmt.Println(unsafe.Pointer(&d)) // 0xfa100
}

内置函数 append 会出发切片的扩容,这个跟C++ vector实现原理有点类似,申请个新的底层数组,拷贝原有数据过去。

// 切片的append操作,返回一个新切片
slice = append(slice, elem1, elem2)
slice = append(slice, anotherSlice...)

// runtime src: slice.go, @fun: growslice
// 扩容策略: 小于1024,每次扩容*2; 大于1024,每次扩容*1.25
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
    newcap = cap
} else {
    if old.len < 1024 {
        newcap = doublecap
    } else {
        for newcap < cap {
            newcap += newcap / 4
        }
    }
}

切片使用起来非常的方便,这都得益于go语言语法级对切片的支持,很容用[:]之类的写法来生成切片实例。还有go的协程也是类似,而库级别的实现远远没有语法级别的支持用起来方便,这都是go的优势所在。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值