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>