Slice usage precautions in go language

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

The slice type in the Go language can be interpreted as a descriptor of the array type, containing three factors:
    1. Pointer to underlying array
    2. Slice the number of elements of the underlying array currently used, that is, the length
    3. The maximum length of the underlying array, which is the capacity
So when we define a slice variable, s: = make ([]int, 5, 10), which points to an underlying array with a maximum length of 10, the current slice s is used to a length of 5. based on the definition of slice, there are a few things to note when using slice: 1. Slicing the sliceSlicing the slice generates a new slice variable, and the new slice and the original slice point to the same underlying array, except that the point of origin may be different, and the length and capacity may vary.
    • The new tile capacity size is changed when there is truncation from the left boundary
    • Left bounds default 0, minimum 0, right boundary default slice length, maximum slice capacity
    • Of course, because pointing to the same underlying array, the operation on the new slice will affect the original slice
Sample Code Https://play.golang.org/p/3GO0cIbZ9u assignment of 2.slice and transfer between functions
A: = []int{1, 2, 3, 4, 5}b: = a
Example code https://play.golang.org/p/lcjiulu-X2 as shown above, a, B points to the same underlying array, and the length and capacity factors are the same, and the operation on B affects a.
Func Main () {    A: = []int{1, 2, 3, 4, 5}    Modifyslice (a)    //[10 2 3 4 5]    FMT. Println (a)}func Modifyslice (s []int) {    s[0] = 10}

Sample code Https://play.golang.org/p/ioOXLoAz3W as shown above, passing slice as a parameter at the time of the function is a value pass, resulting in a new slice, except that the new slice still points to the original underlying array. So the new slice can also change the value of the original slice.
Func Main () {    A: = []int{1, 2, 3, 4, 5}    Modifyslice (a)    //[1 2 3 4 5]    FMT. Println (a)}func Modifyslice (s []int) {    s = []int{10, 20, 30, 40, 50}}

Sample Code HTTPS://PLAY.GOLANG.ORG/P/LBFOVZP-RJ

However, as shown above, within the calling function, the whole of S is assigned a new slice, and the value of a is not changed, because the overall assignment of s back within the Modifyslice function allows s to point to a new underlying array, rather than passing in the array of a point before it. Any operation of S will not affect a.

Append operation of 3.sliceAppend operation is the most easy to step on the pit, the following detailed explanation. Append function Definition: func append (S []t, X ...  T) []tappend basic principle: For a slice variable, if the slice capacity is sufficient, append appends the element to the slice directly on the original underlying array, and if the capacity is insufficient, the append operation generates a new, larger-capacity underlying array. First case:
Func Main () {    A: = Make ([]int, 2, 4)    //Usually the append operation is to assign the return value to itself,    //Here for the convenience of description, did not do    b: = Append (A, 1)    // Changing the value of the first 2 elements of B affects a    b[0] =    //a: [0]    &a[0]: 0x10410020  len:2  cap:4    fmt. Println ("A:", A, "&a[0]:", &a[0], "Len:", Len (a), "cap:", Cap (a))    //b: [0 1]  &b[0]: 0x10410020  len:3  cap:4    fmt. Println ("B:", B, "&b[0]:", &b[0], "Len:", Len (b), "Cap:", Cap (b))}
The example code HTTPS://PLAY.GOLANG.ORG/P/RQQY4U0VCQ, as shown above, append operations on a, if the actual number of new slice after append does not exceed the capacity of the underlying array originally pointed to, the original underlying array is still used : A, the first value of B has the same address, changing the first 2 elements of B also affects a.   In fact, the 3rd bit of the same underlying array (index 2) that A/b points to has become a value of 1, but for slice, in addition to the underlying array, there is a length, a capacity of two factors, the length of a is still 2, so the value of the output of a does not change. Second case:
Func Main () {    A: = Make ([]int, 2, 4)    //Usually the append operation is to assign the return value to itself    //here for the convenience of description, not done    b: = Append (A, 1, 2, 3) 
  //change the value of the first 2 elements of B does not affect a    b[0] =    //a: [0 0]         &a[0]: 0x10410020  len:2  cap:4    fmt. Println ("A:", A, "&a[0]:", &a[0], "Len:", Len (a), "cap:", Cap (a))    //b: [0 1 2 3]  &b[0]: 0x1045 4000  len:5  cap:8    fmt. Println ("B:", B, "&b[0]:", &b[0], "Len:", Len (b), "Cap:", Cap (b))}

Example code Https://play.golang.org/p/e-gvTVx4vZ as shown above, if the append after the new slice that the number of actual elements B is beyond the original a point to the capacity of the underlying array, then will be assigned to b a new underlying array, you can see  , the address of the first element of a, B is already different, and changing the value of the first two elements of B. does not affect a, and the capacity has changed. The third case:
Func Main () {    A: = Make ([]int, 2, 4)    a[0] =    a[1] =    //a: [ten]  &a[0]: 0x10410020  Len:2  cap:4    FMT. Println ("A:", A, "&a[0]:", &a[0], "Len:", Len (a), "cap:", Cap (a))    //For append operation    B: = Append (A[:1], 1) 
  //A: [1]   &a[0]: 0x10410020  len:2  cap:4    fmt. Println ("A:", A, "&a[0]:", &a[0], "Len:", Len (a), "cap:", Cap (a))        //b: [1]   &b[0]: 0x10410020
  len:2  cap:4    fmt. Println ("B:", B, "&b[0]:", &b[0], "Len:", Len (b), "Cap:", Cap (b))}

Example code HTTPS://PLAY.GOLANG.ORG/P/EFB42G5WT9 as shown above, if the number of actual elements of B after append does not exceed the capacity of the underlying array to which the original a is pointing, then a, a and a to the same underlying array. Note At this time the Append object is: A slice after slicing, only take the first value of a, the equivalent of a new slice, the length of 1, and a point to the same underlying array, we call the new slice after the Shard is C bar, then the equivalent of B is actually based on C-Slice for Append, The element is appended directly after the length 1, so the second element of a after append becomes 1. "So be careful when slicing and append operations together," the fourth case:
Func Main () {    A: = Make ([]int, 2, 4)    a[0] =    a[1] =    //a: [ten]       &a[0]: 0x10410020  Len:2  cap:4    FMT. Println ("A:", A, "&a[0]:", &a[0], "Len:", Len (a), "cap:", Cap (a))    //Append Operation    //append is appended after the first element, So to exceed the capacity, at least 4 additional, rather than the previous example of 3    B: = Append (A[:1], 1, 2, 3, 4)    //a: [ten]       &a[0]: 0x10410020  len:2< C14/>cap:4    FMT. Println ("A:", A, "&a[0]:", &a[0], "Len:", Len (a), "cap:", Cap (a))        //b: [1 2 3 4]  &b[0]: 0x1045 4020  len:5  cap:8    fmt. Println ("B:", B, "&b[0]:", &b[0], "Len:", Len (b), "Cap:", Cap (b))}

Example code https://play.golang.org/p/wzNbO9vDJ0 as shown above, this situation is mainly used in comparison with the third case, if the number of elements append more than the original capacity, the direct use of the new underlying array, will not affect a. The above four cases are relatively simple to use, so it is easier to see. Be careful if you pass slice between functions, the calling function takes action with append and may change the original value as follows:
Func Main () {    A: = Make ([]int, 2, 4)    a[0] =    a[1] =    //a: [ten]  &a[0]: 0x10410020  Len:2  cap:4    FMT. Println ("A:", A, "&a[0]:", &a[0], "Len:", Len (a), "cap:", Cap (a))    Testappend (a[:1])    //a: [1]   &A Mp;a[0]: 0x10410020  len:2  cap:4    fmt. Println ("A:", A, "&a[0]:", &a[0], "Len:", Len (a), "cap:", Cap (a))}func testappend (s []int) {    //Append operation C15/>s = Append (s, 1)    //s: [1]  &s[0]: 0x10410020  len:2  cap:4    fmt. Println ("s:", S, "&s[0]:", &s[0], "Len:", Len (s), "cap:", cap (s))}

Sample Code HTTPS://PLAY.GOLANG.ORG/P/MVUZKMBW8U

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

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.