Internal implementation of slices

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Recently busy and have no time to do the column, today decided to write a section on the internal implementation.

Internal implementation

The slice in Go is a data structure, the slice can grow or shorten in its own way, the slice is a very small structure, on my 64-bit computer only 24 bytes, slices have three fields as follows:

type slice struct {array unsafe.Pointerlen   intcap   int}

The first field array points to a pointer to the underlying array, and Len records the number of slice access elements (accessible length) cap allows the number of elements to grow (tile capacity)

Create slices

The go language provides make to create slices, and the slice make source is implemented as follows:

func makeslice(et *_type, len, cap int) slice {// 根据类型大小获取可比较的最大长度maxElements := maxSliceCap(et.size)if len < 0 || uintptr(len) > maxElements {panic(errorString("makeslice: len out of range"))}// 比较容量和长度 比较容量和最大值if cap < len || uintptr(cap) > maxElements {panic(errorString("makeslice: cap out of range"))}// 申请一块内存p := mallocgc(et.size*uintptr(cap), et, true)// 将指针长度容量赋值并返回新切片(这里的长度只是和cap作比较后放入切片结构中)return slice{p, len, cap}}

The first parameter is the type of the data, the second parameter length, the third parameter is the capacity, and if only the length is specified, then the slice's capacity and length are equal, and the length and capacity can be specified separately. (Tiles smaller than the length will be wrong at compile times)

Empty slices

1. The 0 value of slice in Go is nil create a string slice of nil

var s []string

The representation of the nil slice

2. Create an empty slice that is not nil

var s = []string{}//or
var s = make ([]string, 0)

Empty slices that are not nil are not allocated any storage space, and its memory model is as follows:

It is important to note that the append and Len and the cap effects are the same for nil slices and for empty slices that are not nil.

Slice growth

Slices relative to the array, it is possible to grow on demand, the need to expand the tile needs to use append source code as follows:

Func growslice (et *_type, old slice, cap int) Slice {if raceenabled {callerpc: = Getcallerpc (unsafe. Pointer (&et)) Racereadrangepc (Old.array, UIntPtr (Old.len*int (et.size)), Callerpc, FUNCPC (growslice))}if msanenabled {msanread (Old.array, UIntPtr (Old.len*int (et.size)))}if Et.size = = 0 {If cap < Old.cap {Panic (errorstring ( "Growslice:cap out of Range")}//create a non-nil slice return slice{unsafe. Pointer (&zerobase), Old.len, Cap}}newcap: = Old.capdoublecap: = newcap + newcapif cap > doublecap {newcap = cap} El SE {if Old.len < 1024x768 {Newcap = Doublecap} else {for Newcap < cap {Newcap + = Newcap/4}}}var lenmem, Newlenmem, Cap Mem Uintptrconst ptrsize = unsafe. Sizeof ((*byte) (nil)) switch Et.size {case 1:lenmem = uintptr (old.len) Newlenmem = uintptr (cap) Capmem = Roundupsize ( UIntPtr (newcap)) Newcap = Int (capmem) Case ptrsize:lenmem = UIntPtr (old.len) * Ptrsizenewlenmem = uintptr (CAP) * Ptrsizecap MEM = Roundupsize (UIntPtr (newcap) * ptrsize) newcap = Int (capmem/ptrsize) Default:lenmem = UInTptr (old.len) * Et.sizenewlenmem = uintptr (CAP) * Et.sizecapmem = Roundupsize (UIntPtr (newcap) * et.size) newcap = Int (CAPME m/et.size)}if Cap < Old.cap | | UIntPtr (Newcap) > Maxslicecap (et.size) {Panic (errorstring ("Growslice:cap Out of Range")}var p unsafe. Pointerif Et.kind&kindnopointers! = 0 {p = MALLOCGC (Capmem, nil, False) Memmove (p, Old.array, Lenmem) Memclrnoheappointers (Add (P, Newlenmem), Capmem-newlenmem)} else {p = MALLOCGC (Capmem, ET, true) if!writebarrier.enabled {Memmove (P, Old.array, Lenmem)} else {for I: = uintptr (0); i < lenmem; i + = et.size {Typedmemmove (ET, add (P, i), add (OL D.array, i))}}}return slice{p, Old.len, Newcap}}

When the slices are in append, if additional capacity is available, append merges the available elements into the length of the slices, assigns them to them, and if no capacity is available, Append creates a new underlying array, copies the existing values into the new array, and appends the new values.

The source code for copy slices is as follows:

func slicecopy(to, fm slice, width uintptr) int {if fm.len == 0 || to.len == 0 {return 0}n := fm.lenif to.len < n {n = to.len}if width == 0 {return n}if raceenabled {callerpc := getcallerpc(unsafe.Pointer(&to))pc := funcPC(slicecopy)racewriterangepc(to.array, uintptr(n*int(width)), callerpc, pc)racereadrangepc(fm.array, uintptr(n*int(width)), callerpc, pc)}if msanenabled {msanwrite(to.array, uintptr(n*int(width)))msanread(fm.array, uintptr(n*int(width)))}size := uintptr(n) * widthif size == 1 { *(*byte)(to.array) = *(*byte)(fm.array) // known to be a byte pointer} else {memmove(to.array, fm.array, size)}return n}

The copy slice copies the elements from the source slice value (the second parameter value) to the target slice (the first parameter value) and returns the number of copied elements, the copy must be the same two types, and the actual number of copies equals the actual short slice length.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.