Golang Slice Slicing principle

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

The slice in Golang is very powerful, making the array operation very convenient and efficient. The array that is represented in the variable length in development is all slice . But a lot of students of the vague understanding of slice , resulting in the thought that the Golang array is a reference type, the result is in the actual development encountered a lot of pits, so that there are some inexplicable wonderful problems, the data in the array is lost.

Let's start with a detailed understanding of the next slice , which will be very helpful in developing an efficient program.

This is the data structure of slice , it is very simple, a pointer to the real array address ptr , the length of theslice len and the capacity cap .


where len and cap are the values we return in call len (slice) and cap (slice) .

We'll follow Slice 's data structure definition to parse out ptr, len, cap

// 按照定义的数据结构type Slice struct {    ptr   unsafe.Pointer        // Array pointer    len   int               // slice length    cap     int               // slice capacity}

Write a complete program below, trying to convert the Slice memory area in Golang to our defined Slice for parsing

Package Mainimport ("FMT" "unsafe")//data structure by definition type Slice struct {ptr unsafe. Pointer//Array Pointer len Int//Slice length cap int//slice capacity}//Because a pointer calculation is required, you need to get I The length of the NT//32-bit int length = 4//64-bit int length = 8var Intlen = Int (unsafe.  Sizeof (int (0))) Func main () {s: = make ([]int, 10, 20)//use pointer to read slice memory data if Intlen = = 4 {//32 bit M : = * (*[4 + 4*2]byte) (unsafe.) Pointer (&s)) fmt. PRINTLN ("Slice Memory:", M)} else {//64-bit m: = * (*[8 + 8*2]byte) (unsafe. Pointer (&s)) fmt. PRINTLN ("Slice Memory:", M)}//convert slice to custom slice struct slice: = (*slice) (unsafe. Pointer (&s)) fmt. Println ("Slice struct:", slice) fmt. Printf ("Ptr:%v len:%v cap:%v \ n", Slice.ptr, Slice.len, Slice.cap) fmt. Printf ("Golang slice len:%v cap:%v \ n", Len (s), Cap (s)) s[0] = 0 S[1] = 1 S[2] = 2//turn to array output arr: = * (*[3]i NT) (unsafe. Pointer (slice.ptr)) fmt. PRINTLN ("Array values:", arr)//Modify the slice len Slice.len = fmt. Println ("Slice len:", Slice.len) fmt. Println ("Golang Slice len:", Len (s))}

Run a look at the results

$ go run slice.goslice memory: [0 64 6 32 200 0 0 0 10 0 0 0 0 0 0 0 20 0 0 0 0 0 0 0]slice struct: &{0xc820064000 10 20}ptr:0xc820064000 len:10 cap:20golang slice len:10 cap:20array values: [0 1 2]Slice len:  15golang slice len:  15

See, the memory content ofGolang slice , and the value of the custom slice , as well as the RAM pointed to by the pointer in slice , is the actual Array data. When Len is modified in slice , len (s) also changes.

Next, take a couple of examples to understand some of the usage of slice

Declare an array usually using make, you can pass in 2 parameters, or you can pass in 3 parameters, the first is the data type, the second is Len , and the third is the cap . If you do not wear a third argument, Cap=len ,append can be used to append data to the end of the array.

This is a append test.

// 每次cap改变,指向array的ptr就会变化一次s := make([]int, 1)fmt.Printf("len:%d cap: %d array ptr: %v \n", len(s), cap(s), *(*unsafe.Pointer)(unsafe.Pointer(&s)))for i := 0; i < 5; i++ {    s = append(s, i)    fmt.Printf("len:%d cap: %d array ptr: %v \n", len(s), cap(s), *(*unsafe.Pointer)(unsafe.Pointer(&s)))}fmt.Println("Array:", s)

Run results

len:1 cap: 1 array ptr: 0xc8200640f0len:2 cap: 2 array ptr: 0xc820064110len:3 cap: 4 array ptr: 0xc8200680c0len:4 cap: 4 array ptr: 0xc8200680c0len:5 cap: 8 array ptr: 0xc82006c080len:6 cap: 8 array ptr: 0xc82006c080Array: [0 0 1 2 3 4]

See, every time the CAP changes, the pointer to array memory is changing. When using append , if cap==len this time, it will open up a new piece of larger memory, and then copy the previous data.

The actual go in append to enlarge the CAP is regular. In cases where the cap is less than 1024, it expands to 2 * caps each time, and expands to the 1.25 * Cap each time it is greater than 1024. So the above test has a cap change of 1, 2, 4, 8

In practice, we'd better anticipate a cap in advance, so that when using append, you can avoid repeatedly reallocating the data before the memory is copied, reducing unnecessary performance consumption.

Create slices

s := []int{1, 2, 3, 4, 5}fmt.Printf("len:%d cap: %d array ptr: %v \n", len(s), cap(s), *(*unsafe.Pointer)(unsafe.Pointer(&s)))fmt.Println("Array:", s)s1 := s[1:3]fmt.Printf("len:%d cap: %d array ptr: %v \n", len(s1), cap(s1), *(*unsafe.Pointer)(unsafe.Pointer(&s1)))fmt.Println("Array", s1)

Run results

len:5 cap: 5 array ptr: 0xc820012210Array: [1 2 3 4 5]len:2 cap: 4 array ptr: 0xc820012218Array [2 3]

Creates a new slice based on a slice S1 , and the new Slice's ptr points to the memory address of the s1[0] data. You can see the pointer address 0xc820012210 and 0xc820012218 8byte is exactly an int type length, the CAP also becomes 4

It's written here, to summarize, the structure of the slice is a pointer to the data, length and capacity. Copy the slice, or create a new slice on the slice, and the pointer in the slice points to the same data memory area.

Know the principle of slicing can be in development to avoid errors, I hope this blog can bring you help.

Reference: Https://blog.golang.org/go-slices-usage-and-internals

Attach the data structure definition of slice in Go source code

type slice struct {    array unsafe.Pointer    len   int    cap   int}
Related Article

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.