首先我们来看一段代码:
package main
import (
"fmt"
"unsafe"
)
func main() {
var a int
var b int8
var c int16
var d int32
var e int64
slice := make([]int, 0)
slice = append(slice, 1)
fmt.Printf("int:%dnint8:%dnint16:%dnint32:%dnint64:%dn", unsafe.Sizeof(a), unsafe.Sizeof(b), unsafe.Sizeof(c), unsafe.Sizeof(d), unsafe.Sizeof(e))
fmt.Printf("slice:%d", unsafe.Sizeof(slice))
}
该程序输出golang中常用数据类型占多少byte,输出结果是:
int:8
int8:1
int16:2
int32:4
int64:8
slice:24
我们可以看到slice占24byte,为什么会占24byte,这就跟slice底层定义的结构有关,我们在golang的runtime/slice.go中可以找到slice的结构定义,如下:
type slice struct {
array unsafe.Pointer//指向底层数组的指针
len int//切片的长度
cap int//切片的容量
}
我们可以看到slice中定义了三个变量,一个是指向底层数字的指针array,另外两个是切片的长度len和切片的容量cap。
slice初始化
简单了解了slice的底层结构后,我们来看下slice的初始化,在golang中slice有多重初始化方式,在这里我们就不一一介绍了,我们主要关注slice在底层是如何初始化的,首先我们来看一段代码:
package main
import "fmt"
func main() {
slice := make([]int, 0)
slice = append(slice, 1)
fmt.Println(slice, len(slice), cap(slice))
}
很简单的一段代码,make一个slice,往slice中append一个一个1,打印slice内容,长度和容量,接下来我们利用gotool提供的工具将以上代码反汇编:
go tool compile -S slice.go
得到汇编代码如下(截取部分):
0x0000 00000 (slice.go:8) TEXT "".main(SB), ABIInternal, $152-0
0x0000 00000 (slice.go:8) MOVQ (TLS), CX
0x0009 00009 (slice.go:8) LEAQ -24(SP), AX
0x000e 00014 (slice.go:8) CMPQ AX, 16(CX)
0x0012 00018 (slice.go:8) JLS 375
0x0018 00024 (slice.go:8) SUBQ $152, SP
0x001f 00031 (slice.go:8) MOVQ BP, 144(SP)
0x0027 00039 (slice.go:8) LEAQ 144(SP), BP
0x002f 00047 (slice.go:8) FUNCDATA $0, gclocals- f14a5bc6d08bc46424827f54d2e3f8ed(SB)//编译器产生,用于保存一些垃圾收集相关的信息
0x002f 00047 (slice.go:8) FUNCDATA $1, gclocals- 3e7bd269c75edba02eda3b9069a96409(SB)
0x002f 00047 (slice.go:8) FUNCDATA $2, gclocals- f6aec3988379d2bd21c69c093370a150(SB)
0x002f 00047 (slice.go:8) FUNCDATA $3, "".main.stkobj(SB)
0x002f 00047 (slice.go:9) PCDATA $0, $1
0x002f 00047 (slice.go:9) PCDATA $1, $0
0x002f 00047 (slice.go:9) LEAQ type.int(SB), AX
0x0036 00054 (slice.go:9) PCDATA $0, $0
0x0036 00054 (slice.go:9) MOVQ AX, (SP)
0x003a 00058 (slice.go:9) XORPS X0, X0
0x003d 00061 (slice.go:9) MOVUPS X0, 8(SP)
0x0042 00066 (slice.go:9) CALL runtime.makeslice(SB)//初始化slice
0x0047 00071 (slice.go:9) PCDATA $0, $1
0x0047 00071 (slice.go:9) MOVQ 24(SP), AX
0x004c 00076 (slice.go:10) PCDATA $0, $2
0x004c 00076 (slice.go:10) LEAQ type.int(SB), CX
0x0053 00083 (slice.go:10) PCDATA $0, $1
0x0053 00083 (slice.go:10) MOVQ CX, (SP)
0x0057 00087 (slice.go:10) PCDATA $0, $0
0x0057 00087 (slice.go:10) MOVQ AX, 8(SP)
0x005c 00092 (slice.go:10) XORPS X0, X0
0x005f 00095 (slice.go:10) MOVUPS X0, 16(SP)
0x0064 00100 (slice.go:10) MOVQ $1, 32(SP)
0x006d 00109 (slice.go:10) CALL runtime.growslice(SB)//append操作
0x0072 00114 (slice.go:10) PCDATA $0, $1
0x0072 00114 (slice.go:10) MOVQ 40(SP), AX
0x0077 00119 (slice.go:10) MOVQ 48(SP), CX
0x007c 00124 (slice.go:10) MOVQ 56(SP), DX
0x0081 00129 (slice.go:10) MOVQ DX, "".slice.cap+72(SP)
0x0086 00134 (slice.go:10) MOVQ $1, (AX)
0x008d 00141 (slice.go:11) PCDATA $0, $0
0x008d 00141 (slice.go:11) MOVQ AX, (SP)
0x0091 00145 (slice.go:10) LEAQ 1(CX), AX
0x0095 00149 (slice.go:10) MOVQ AX, "".slice.len+64(SP)
0x009a 00154 (slice.go:11) MOVQ AX, 8(SP)
0x009f 00159 (slice.go:11) MOVQ DX, 16(SP)
0x00a4 00164 (slice.go:11) CALL runtime.convTslice(SB)//类型转换
0x00a9 00169 (slice.go:11) PCDATA $0, $1
0x00a9 00169 (slice.go:11) MOVQ 24(SP), AX
0x00ae 00174 (slice.go:11) PCDATA $0, $0
0x00ae 00174 (slice.go:11) PCDATA $1, $1
0x00ae 00174 (slice.go:11) MOVQ AX, ""..autotmp_33+88(SP)
0x00b3 00179 (slice.go:11) MOVQ "".slice.len+64(SP), CX
0x00b8 00184 (slice.go:11) MOVQ CX, (SP)
0x00bc 00188 (slice.go:11) CALL runtime.convT64(SB)
0x00c1 00193 (slice.go:11) PCDATA $0, $1
0x00c1 00193 (slice.go:11) MOVQ 8(SP), AX
0x00c6 00198 (slice.go:11) PCDATA $0, $0
0x00c6 00198 (slice.go:11) PCDATA $1, $2
0x00c6 00198 (slice.go:11) MOVQ AX, ""..autotmp_34+80(SP)
0x00cb 00203 (slice.go:11) MOVQ "".slice.cap+72(SP), CX
0x00d0 00208 (slice.go:11) MOVQ CX, (SP)
0x00d4 00212 (slice.go:11) CALL runtime.convT64(SB)
0x00d9 00217 (slice.go:11) PCDATA $0, $1
0x00d9 00217 (slice.go:11) MOVQ 8(SP), AX
0x00de 00222 (slice.go:11) PCDATA $1, $3
0x00de 00222 (slice.go:11) XORPS X0, X0
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。