Array slices in the Go language: mutable array of Maverick

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

First look at the slice in the go language, think is a very good implementation of variable array, directly at the level of language grammar support, operating compared to Java in the ArrayList convenient a lot. But after the use of a period of time, feel that this thing buried a lot, the use of the way and ArrayList are also very different, in the use of extra attention.

Data structure of Slice

First of all, the slice data structure, the source code can be found on Google Code, http://code.google.com/p/go/source/browse/src/pkg/runtime/runtime.h

struct slice{                              byte*   array;  Actual data    Uintgo  len;    Number of elements    Uintgo  caps;    Allocated number of elements};

You can see that there are three main messages saved:

    • A pointer to the native array
    • Number of elements
    • The storage space allocated by the array

Basic operation of Slice

There are several ways to generate slices in go, which also correspond to the basic operation of slice, after each operation go hides a lot of detail, if it is not enough to know, it is easy to stumble over these pits when used.

1.make function Generation

This is the most basic, most primitive way to generate slice slices, and the tiles generated by other means are ultimately done in this way. Because in any case it is necessary to fill the three most basic information of the slice structure above.

By finding the source code, the discovery is finally implemented by the following C code:

static void Makeslice1 (Slicetype *t, Intgo len, Intgo cap, Slice *ret) {    ret->len = len;    Ret->cap = cap;    Ret->array = Runtime Cnewarray (T->elem, CAP);}

The Make function is written when generating slice:

var Slice1 = make ([]int, 0, 5) var slice2 = make ([]int, 5, 5)//Omit Len notation, len default equals cap, equivalent to make ([]int, 5, 5) var slice3 = make ([ ]int, 5)

This simple writing is a bit of a pit dad, if you write make ([]int, 5), go will default to the array length Len as the capacity of slice, according to the above example, the resulting structure:[0 0 0 0 0]

2. Slicing an array first look at the following code:

Arr: = [5]int{1, 2, 3, 4, 5}slice: = Arr[3:5]//  slice:[4, 5]slice[0] = 0        //slice:[0, 5]fmt. Println (Slice) fmt. Println (arr)

Output Result:

[0 5] [1 2 3 0 5]

As can be seen from the above, the array is sliced operation, the resulting slice of the arrays pointer actually point to a position of the original array, the equivalent of C code in the original array to intercept the creation of a new array [2]arrnew, the array pointer to arr[3], so change the slice 0 subscript corresponding element value, In fact, it changes the value of the element in the corresponding array position 3 of the original array.

This blog post on this question is more detailed: a "pit" of Append for Go slice

3. Append an array or slice

Personally, this append is a place where the go language is not very elegant, such as the append of a slice must be written like this: slice = append(slice, 1) . To put it bluntly, a new reference must be re-assigned to slice when a slice is append. If it's just grammatical weird, the problem is fine, but the code is a little cumbersome to write. But the reality is that this append operation caused a lot of problems, careless easy to go to append buried in the pit.

Let's look at a strange phenomenon:

var slicea = make ([]int, 0, 5) Sliceb: = Append (Slicea, 1) fmt. Println (Slicea) fmt. Println (SLICEB)

The output is:

[][1]

It is very difficult to understand the results just see, clearly declared that the capacity is 5 of the slice, now Slicea len is 0, far from the capacity to reach the slice. It is supposed that the append operation of the slicea does not need to re-apply a new large-capacity array without reaching the tile capacity, only to modify the value of the element within the original array. Also, the Go function is a reference pass when the slice is transferred, so that the SLICEB and slicea should output the same. It's confusing for a long time to see such a result, does every append operation reallocate the array?

The answer is certainly not the case, if so, go will not have to mix, performance will certainly be problematic. The following from GO implementation append source code to find the answer, source location in: http://code.google.com/p/go/source/browse/src/pkg/runtime/slice.c code is very long, Only the key fragments are captured here to illustrate the problem:

void Runtime Appendslice (Slicetype *t, Slice x, Slice y, Slice ret) {    Intgo m = x.len+y.len;    void *pc;    if (M > X.cap)        growslice1 (t, X, M, &ret);    else        ret = x;    Read X[:len]    if (M > X.cap)        runtime Racereadrangepc (X.array, x.len*w, PC, runtime Appendslice);    Read y    runtime Racereadrangepc (Y.array, y.len*w, PC, runtime Appendslice);    Write X[len (x): Len (x) +len (y)]    if (M <= x.cap)        runtime Racewriterangepc (ret.array+ret.len*w, Y.len*w, PC, runtime Appendslice);    Ret.len + = Y.len;    FLUSH (&ret);}

function definitions appendslice(SliceType *t, Slice x, Slice y, Slice ret) , corresponding slice3 = append(slice1, slice1...) operations, respectively: the element type in the array, Slice1, Slice2, Slice3. Although the second argument cannot be slice in the append () syntax, the second parameter is actually a mutable parameter elems ...Type that can transmit the scattered array, so go is also converted to slice when processing.

It is clear from the code above that if X.len + Y.len exceeds x.cap, the new slice will be re-expanded, and if X.len + Y.len has not exceeded x.cap, then the element is filled in the original slice's array. Then this is consistent with our rational understanding. Can eliminate the previous misunderstanding of the go append worry. What's the problem?

The above ignores a point, append function is the code of Go, not the implementation of the direct language level C, in the implementation of C also added the go language of their own processing, in the/pkg/builtin/bulitin.go has a function definition. Here I can only assume that on the go level to Sclicea do some covert processing, go how to call C's underlying implementation, I do not know very well, here can only be analyzed here. After understanding later to add this blog, if there are friends who know, also very grateful to you to tell me.

4. Declaring an array with no length

Declaring a non-length array is actually declaring a mutable array, which is the slice slice. Only the Len and cap of this slice are 0. This method is very convenient to write, if you do not understand the implementation behind it, then this is the worst performance. Because it leads to frequent re-application of slice, and the need to copy the elements from the original array to a new large-capacity array. The step size for each reallocation of the array capacity is len*2, and if you do n append, you need to re-request the memory and copy costs LOG2 (n) times.

A later article will continue to cover some of the differences between slices and arrays:

The difference between go slice and array

You can also visit my Raspberry Pi blog address:

http://www.codeforfun.info/

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.