2012-10-07 102 views
15

我最近拿起去,現在我用下面的代碼混淆:重新切片切片Golang

package main 

import "fmt" 

func main() { 
    a := make([]int, 5) 
    printSlice("a", a) 
    b := make([]int, 0, 5) 
    printSlice("b", b) 
    c := b[:2] 
    printSlice("c", c) 
    d := c[2:5] 
    printSlice("d", d) 
} 

func printSlice(s string, x []int) { 
    fmt.Printf("%s len=%d cap=%d %v\n", 
     s, len(x), cap(x), x) 
} 

而結果:

a len=5 cap=5 [0 0 0 0 0] 
b len=0 cap=5 [] 
c len=2 cap=5 [0 0] //why the capacity of c not 2 but 5 instead 
d len=3 cap=3 [0 0 0] 

任何幫助的感謝。

+0

自己的能力切片即將到來(去1.2)。請參閱[我的答案](http://stackoverflow.com/a/18911267/6309) – VonC

回答

20

c是取自陣列b的切片。這不是一個副本,而是b的2個第一個元素的窗口。

由於b的容量爲5,c可以擴展到另外3個地方(事實上,它創建了一個新的切片,但是在內存中的同一個地方)。

切片的最大容量是底層陣列的容量減去片的開始的陣列中的位置:

array : [0 0 0 0 0 0 0 0 0 0 0 0] 
array : <---- capacity ---> 
slice :  [0 0 0 0] 
slice :  <---- capacity ---> 

也許這程序將使其更清楚,c和d是

func main() { 
    b := make([]int, 0, 5) 
    c := b[:2] 
    d := c[1:5] // this is equivalent to d := b[1:5] 
    d[0] = 1 
    printSlice("c", c) 
    printSlice("d", d) 
} 

輸出:

c len=2 cap=5 [0 1] // modifying d has modified c 
d len=4 cap=4 [1 0 0 0] 
+2

感謝您的有用答案。 – Coder

+1

那麼b也會有影響嗎? – Coder

+1

是的。但是你不會看到它,因爲長度是0。 –

11

需要注意的是,在短短乙級以上的窗戶請轉1.2(Q4 2013, 1.2rc1 is available now),,您可以將其關聯到自己的容量爲的片(而不是從底層陣列推導的容量)。

請參閱「Three-index slices」和design document

甲切割操作通過描述已創建陣列或切片的連續部分創建一個新的切片:

var array [10]int 
slice := array[2:4] 

切片的容量是元件的最大數目片斷可能會持有,即使在重組之後;它反映了底層數組的大小。
在這個例子中,片可變的容量爲8

(容量底層數組的減去片的開始的陣列中的位置)

array : [0 0 0 0 0 0 0 0 0 0] 
array : <---- capacity ---> 
slice : [0 0] 
slice : <-- capacity --> 8 (10-2) 

轉到1.2增加了新的語法來允許分片操作到指定容量以及長度
第二個冒號引入了容量值,該值必須小於或等於源片或陣列的容量,並對原點進行調整。

例如,

slice = array[2:4:6] 

array : [0 0 0 0 0 0 0 0 0 0] 
array : <---- capacity ---> 10 
slice : [0 0] 
slice : <- cap->   4 (6-2) 

設置切片具有相同的長度在前面的示例,但現在它的容量只有4個元件(6-2)。
不可能使用這個新的切片值來訪問原始數組的最後兩個元素。

的主要論點是給程序員更多的控制權append

a[i : j : k] 

這片有:

  • 指數從0開始
  • 長度等於j - i
  • 容量等於k - i

評價恐慌,如果i <= j <= k <= cap(a)是不是真的