github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/doc/articles/slices_usage_and_internals.html (about)

     1  <!--{
     2  	"Title": "Slices: usage and internals",
     3  	"Template": true
     4  }-->
     5  
     6  <p>
     7  Go's slice type provides a convenient and efficient means of working with
     8  sequences of typed data. Slices are analogous to arrays in other languages, but
     9  have some unusual properties. This article will look at what slices are and how
    10  they are used.
    11  </p>
    12  
    13  <p>
    14  <b>Arrays</b>
    15  </p>
    16  
    17  <p>
    18  The slice type is an abstraction built on top of Go's array type, and so to
    19  understand slices we must first understand arrays.
    20  </p>
    21  
    22  <p>
    23  An array type definition specifies a length and an element type. For example,
    24  the type <code>[4]int</code> represents an array of four integers. An array's
    25  size is fixed; its length is part of its type (<code>[4]int</code> and
    26  <code>[5]int</code> are distinct, incompatible types). Arrays can be indexed in
    27  the usual way, so the expression <code>s[n]</code> accesses the <i>n</i>th
    28  element, starting from zero.
    29  </p>
    30  
    31  <pre>
    32  var a [4]int
    33  a[0] = 1
    34  i := a[0]
    35  // i == 1
    36  </pre>
    37  
    38  <p>
    39  Arrays do not need to be initialized explicitly; the zero value of an array is
    40  a ready-to-use array whose elements are themselves zeroed:
    41  </p>
    42  
    43  <pre>
    44  // a[2] == 0, the zero value of the int type
    45  </pre>
    46  
    47  <p>
    48  The in-memory representation of <code>[4]int</code> is just four integer values laid out sequentially:
    49  </p>
    50  
    51  <p>
    52  <img src="slice-array.png">
    53  </p>
    54  
    55  <p>
    56  Go's arrays are values. An array variable denotes the entire array; it is not a
    57  pointer to the first array element (as would be the case in C).  This means
    58  that when you assign or pass around an array value you will make a copy of its
    59  contents. (To avoid the copy you could pass a <i>pointer</i> to the array, but
    60  then that's a pointer to an array, not an array.) One way to think about arrays
    61  is as a sort of struct but with indexed rather than named fields: a fixed-size
    62  composite value.
    63  </p>
    64  
    65  <p>
    66  An array literal can be specified like so:
    67  </p>
    68  
    69  <pre>
    70  b := [2]string{"Penn", "Teller"}
    71  </pre>
    72  
    73  <p>
    74  Or, you can have the compiler count the array elements for you:
    75  </p>
    76  
    77  <pre>
    78  b := [...]string{"Penn", "Teller"}
    79  </pre>
    80  
    81  <p>
    82  In both cases, the type of <code>b</code> is <code>[2]string</code>.
    83  </p>
    84  
    85  <p>
    86  <b>Slices</b>
    87  </p>
    88  
    89  <p>
    90  Arrays have their place, but they're a bit inflexible, so you don't see them
    91  too often in Go code. Slices, though, are everywhere. They build on arrays to
    92  provide great power and convenience.
    93  </p>
    94  
    95  <p>
    96  The type specification for a slice is <code>[]T</code>, where <code>T</code> is
    97  the type of the elements of the slice. Unlike an array type, a slice type has
    98  no specified length.
    99  </p>
   100  
   101  <p>
   102  A slice literal is declared just like an array literal, except you leave out
   103  the element count:
   104  </p>
   105  
   106  <pre>
   107  letters := []string{"a", "b", "c", "d"}
   108  </pre>
   109  
   110  <p>
   111  A slice can be created with the built-in function called <code>make</code>,
   112  which has the signature,
   113  </p>
   114  
   115  <pre>
   116  func make([]T, len, cap) []T
   117  </pre>
   118  
   119  <p>
   120  where T stands for the element type of the slice to be created. The
   121  <code>make</code> function takes a type, a length, and an optional capacity.
   122  When called, <code>make</code> allocates an array and returns a slice that
   123  refers to that array.
   124  </p>
   125  
   126  <pre>
   127  var s []byte
   128  s = make([]byte, 5, 5)
   129  // s == []byte{0, 0, 0, 0, 0}
   130  </pre>
   131  
   132  <p>
   133  When the capacity argument is omitted, it defaults to the specified length.
   134  Here's a more succinct version of the same code:
   135  </p>
   136  
   137  <pre>
   138  s := make([]byte, 5)
   139  </pre>
   140  
   141  <p>
   142  The length and capacity of a slice can be inspected using the built-in
   143  <code>len</code> and <code>cap</code> functions.
   144  </p>
   145  
   146  <pre>
   147  len(s) == 5
   148  cap(s) == 5
   149  </pre>
   150  
   151  <p>
   152  The next two sections discuss the relationship between length and capacity.
   153  </p>
   154  
   155  <p>
   156  The zero value of a slice is <code>nil</code>. The <code>len</code> and
   157  <code>cap</code> functions will both return 0 for a nil slice.
   158  </p>
   159  
   160  <p>
   161  A slice can also be formed by "slicing" an existing slice or array. Slicing is
   162  done by specifying a half-open range with two indices separated by a colon. For
   163  example, the expression <code>b[1:4]</code> creates a slice including elements
   164  1 through 3 of <code>b</code> (the indices of the resulting slice will be 0
   165  through 2).
   166  </p>
   167  
   168  <pre>
   169  b := []byte{'g', 'o', 'l', 'a', 'n', 'g'}
   170  // b[1:4] == []byte{'o', 'l', 'a'}, sharing the same storage as b
   171  </pre>
   172  
   173  <p>
   174  The start and end indices of a slice expression are optional; they default to zero and the slice's length respectively:
   175  </p>
   176  
   177  <pre>
   178  // b[:2] == []byte{'g', 'o'}
   179  // b[2:] == []byte{'l', 'a', 'n', 'g'}
   180  // b[:] == b
   181  </pre>
   182  
   183  <p>
   184  This is also the syntax to create a slice given an array:
   185  </p>
   186  
   187  <pre>
   188  x := [3]string{"Лайка", "Белка", "Стрелка"}
   189  s := x[:] // a slice referencing the storage of x
   190  </pre>
   191  
   192  <p>
   193  <b>Slice internals</b>
   194  </p>
   195  
   196  <p>
   197  A slice is a descriptor of an array segment. It consists of a pointer to the
   198  array, the length of the segment, and its capacity (the maximum length of the
   199  segment).
   200  </p>
   201  
   202  <p>
   203  <img src="slice-struct.png">
   204  </p>
   205  
   206  <p>
   207  Our variable <code>s</code>, created earlier by <code>make([]byte, 5)</code>,
   208  is structured like this:
   209  </p>
   210  
   211  <p>
   212  <img src="slice-1.png">
   213  </p>
   214  
   215  <p>
   216  The length is the number of elements referred to by the slice. The capacity is
   217  the number of elements in the underlying array (beginning at the element
   218  referred to by the slice pointer). The distinction between length and capacity
   219  will be made clear as we walk through the next few examples.
   220  </p>
   221  
   222  <p>
   223  As we slice <code>s</code>, observe the changes in the slice data structure and
   224  their relation to the underlying array:
   225  </p>
   226  
   227  <pre>
   228  s = s[2:4]
   229  </pre>
   230  
   231  <p>
   232  <img src="slice-2.png">
   233  </p>
   234  
   235  <p>
   236  Slicing does not copy the slice's data. It creates a new slice value that
   237  points to the original array. This makes slice operations as efficient as
   238  manipulating array indices. Therefore, modifying the <i>elements</i> (not the
   239  slice itself) of a re-slice modifies the elements of the original slice:
   240  </p>
   241  
   242  <pre>
   243  d := []byte{'r', 'o', 'a', 'd'}
   244  e := d[2:] 
   245  // e == []byte{'a', 'd'}
   246  e[1] = 'm'
   247  // e == []byte{'a', 'm'}
   248  // d == []byte{'r', 'o', 'a', 'm'}
   249  </pre>
   250  
   251  <p>
   252  Earlier we sliced <code>s</code> to a length shorter than its capacity. We can
   253  grow s to its capacity by slicing it again:
   254  </p>
   255  
   256  <pre>
   257  s = s[:cap(s)]
   258  </pre>
   259  
   260  <p>
   261  <img src="slice-3.png">
   262  </p>
   263  
   264  <p>
   265  A slice cannot be grown beyond its capacity. Attempting to do so will cause a
   266  runtime panic, just as when indexing outside the bounds of a slice or array.
   267  Similarly, slices cannot be re-sliced below zero to access earlier elements in
   268  the array.
   269  </p>
   270  
   271  <p>
   272  <b>Growing slices (the copy and append functions)</b>
   273  </p>
   274  
   275  <p>
   276  To increase the capacity of a slice one must create a new, larger slice and
   277  copy the contents of the original slice into it. This technique is how dynamic
   278  array implementations from other languages work behind the scenes. The next
   279  example doubles the capacity of <code>s</code> by making a new slice,
   280  <code>t</code>, copying the contents of <code>s</code> into <code>t</code>, and
   281  then assigning the slice value <code>t</code> to <code>s</code>:
   282  </p>
   283  
   284  <pre>
   285  t := make([]byte, len(s), (cap(s)+1)*2) // +1 in case cap(s) == 0
   286  for i := range s {
   287          t[i] = s[i]
   288  }
   289  s = t
   290  </pre>
   291  
   292  <p>
   293  The looping piece of this common operation is made easier by the built-in copy
   294  function. As the name suggests, copy copies data from a source slice to a
   295  destination slice. It returns the number of elements copied.
   296  </p>
   297  
   298  <pre>
   299  func copy(dst, src []T) int
   300  </pre>
   301  
   302  <p>
   303  The <code>copy</code> function supports copying between slices of different
   304  lengths (it will copy only up to the smaller number of elements). In addition,
   305  <code>copy</code> can handle source and destination slices that share the same
   306  underlying array, handling overlapping slices correctly.
   307  </p>
   308  
   309  <p>
   310  Using <code>copy</code>, we can simplify the code snippet above:
   311  </p>
   312  
   313  <pre>
   314  t := make([]byte, len(s), (cap(s)+1)*2)
   315  copy(t, s)
   316  s = t
   317  </pre>
   318  
   319  <p>
   320  A common operation is to append data to the end of a slice. This function
   321  appends byte elements to a slice of bytes, growing the slice if necessary, and
   322  returns the updated slice value:
   323  </p>
   324  
   325  {{code "/doc/progs/slices.go" `/AppendByte/` `/STOP/`}}
   326  
   327  <p>
   328  One could use <code>AppendByte</code> like this:
   329  </p>
   330  
   331  <pre>
   332  p := []byte{2, 3, 5}
   333  p = AppendByte(p, 7, 11, 13)
   334  // p == []byte{2, 3, 5, 7, 11, 13}
   335  </pre>
   336  
   337  <p>
   338  Functions like <code>AppendByte</code> are useful because they offer complete
   339  control over the way the slice is grown. Depending on the characteristics of
   340  the program, it may be desirable to allocate in smaller or larger chunks, or to
   341  put a ceiling on the size of a reallocation.
   342  </p>
   343  
   344  <p>
   345  But most programs don't need complete control, so Go provides a built-in
   346  <code>append</code> function that's good for most purposes; it has the
   347  signature
   348  </p>
   349  
   350  <pre>
   351  func append(s []T, x ...T) []T 
   352  </pre>
   353  
   354  <p>
   355  The <code>append</code> function appends the elements <code>x</code> to the end
   356  of the slice <code>s</code>, and grows the slice if a greater capacity is
   357  needed.
   358  </p>
   359  
   360  <pre>
   361  a := make([]int, 1)
   362  // a == []int{0}
   363  a = append(a, 1, 2, 3)
   364  // a == []int{0, 1, 2, 3}
   365  </pre>
   366  
   367  <p>
   368  To append one slice to another, use <code>...</code> to expand the second
   369  argument to a list of arguments.
   370  </p>
   371  
   372  <pre>
   373  a := []string{"John", "Paul"}
   374  b := []string{"George", "Ringo", "Pete"}
   375  a = append(a, b...) // equivalent to "append(a, b[0], b[1], b[2])"
   376  // a == []string{"John", "Paul", "George", "Ringo", "Pete"}
   377  </pre>
   378  
   379  <p>
   380  Since the zero value of a slice (<code>nil</code>) acts like a zero-length
   381  slice, you can declare a slice variable and then append to it in a loop:
   382  </p>
   383  
   384  {{code "/doc/progs/slices.go" `/Filter/` `/STOP/`}}
   385  
   386  <p>
   387  <b>A possible "gotcha"</b>
   388  </p>
   389  
   390  <p>
   391  As mentioned earlier, re-slicing a slice doesn't make a copy of the underlying
   392  array. The full array will be kept in memory until it is no longer referenced.
   393  Occasionally this can cause the program to hold all the data in memory when
   394  only a small piece of it is needed.
   395  </p>
   396  
   397  <p>
   398  For example, this <code>FindDigits</code> function loads a file into memory and
   399  searches it for the first group of consecutive numeric digits, returning them
   400  as a new slice.
   401  </p>
   402  
   403  {{code "/doc/progs/slices.go" `/digit/` `/STOP/`}}
   404  
   405  <p>
   406  This code behaves as advertised, but the returned <code>[]byte</code> points
   407  into an array containing the entire file. Since the slice references the
   408  original array, as long as the slice is kept around the garbage collector can't
   409  release the array; the few useful bytes of the file keep the entire contents in
   410  memory.
   411  </p>
   412  
   413  <p>
   414  To fix this problem one can copy the interesting data to a new slice before
   415  returning it:
   416  </p>
   417  
   418  {{code "/doc/progs/slices.go" `/CopyDigits/` `/STOP/`}}
   419  
   420  <p>
   421  A more concise version of this function could be constructed by using
   422  <code>append</code>. This is left as an exercise for the reader.
   423  </p>
   424  
   425  <p>
   426  <b>Further Reading</b>
   427  </p>
   428  
   429  <p>
   430  <a href="/doc/effective_go.html">Effective Go</a> contains an
   431  in-depth treatment of <a href="/doc/effective_go.html#slices">slices</a>
   432  and <a href="/doc/effective_go.html#arrays">arrays</a>, 
   433  and the Go <a href="/doc/go_spec.html">language specification</a>
   434  defines <a href="/doc/go_spec.html#Slice_types">slices</a> and their
   435  <a href="/doc/go_spec.html#Length_and_capacity">associated</a>
   436  <a href="/doc/go_spec.html#Making_slices_maps_and_channels">helper</a>
   437  <a href="/doc/go_spec.html#Appending_and_copying_slices">functions</a>.
   438  </p>