2017-10-08 86 views
7

我剛開始瀏覽gotour,並遇到關於切片默認章節的問題。延長左側的切片長度

package main 

import "fmt" 

func main() { 
    s := []int{2, 3, 5, 7, 11, 13} 

    s = s[1:4] 
    fmt.Println(s) // [3 5 7] 
    fmt.Println(len(s)) // 3 

    s = s[:4] 
    fmt.Println(s) // [3 5 7 11] 
    fmt.Println(len(s)) // 4 

} 

我可以通過選擇大於或等於上一個切片長度的索引來擴展右邊的切片長度。例如s[:4]所以我可以達到條目11。但是,當我使用s[-1:]在左側擴展併到達條目2時,編譯器給我提供了錯誤invalid slice index -1 (index must be non-negative)。 執行s=s[1:4]後,是否可以延長左側的切片長度以達到條目2

回答

1

首先,要回答你的問題,沒有它不可能使用負的索引或訪問這些數據,除了通過保持原片的副本。

然而,這是一個有趣的問題,因爲這裏有一個不一致的地方,你已經指出,這可能更多的是你問的。如果你有一個分片開始爲here

a := []int{2, 3, 5, 7, 11, 13} 
fmt.Println(a,len(a),cap(a)) 

[2 3 5 7 11 13] 6 6

而採取的只是中間

b := a[1:2] 
fmt.Println(b,len(b),cap(b)) 

[3] 1 5

片你不允許訪問索引中的原始數據過去那種如你所料:

fmt.Println(b[3]) 

panic: runtime error: index out of range

不允許您從一開始索引之前重新劃分爲包括數據再次:

d := b[-1:] 

invalid slice index -1 (index must be non-negative)

但你允許重新劃分爲包括數據的len個後再次達到上限,這是一個有點奇怪:

// This is beyond the length of b, you can't index those, 
// but you can access them by reslicing 
c := b[:5] 

[3 5 7 11 13] 5 5

這有點不一致,因爲對切片數據的大多數其他操作受數據和len的偏移限制,而不是上限和原始數據長度。然而,這在規範中有明確規定,可能僅僅是片斷代表原始陣列上的視圖而不是提供對該數據訪問的有意設計決策的一種人造物。如果你可以回到原始存儲器,它可能會很好,因爲它仍然在內存中,但是看起來你只能看到陣列的末端達到了上限,而不是在你已經切片一次後纔開始。從spec關於切片指標限制:

For arrays or strings, the indices are in range if 0 <= low <= high <= len(a), otherwise they are out of range. For slices, the upper index bound is the slice capacity cap(a) rather than the length. A constant index must be non-negative and representable by a value of type int; for arrays or constant strings, constant indices must also be in range. If both indices are constant, they must satisfy low <= high. If the indices are out of range at run time, a run-time panic occurs.

這可能會更好是安全的,使用原來的切片上的數據創建不同的看法,而不是依賴於這種行爲。

6

當您從底層數組的第二個索引創建一個新切片時,就像您使用s = s[1:4]一樣,那麼您已經失去了對底層數組中第一個元素的引用。

而且由於切片運算符s[i:j]需要i >= 0,因此您無法再通過進一步切片化現有切片來訪問原始數組中的第一個元素。

你可以保留原有的陣列周圍,但是:

func main() { 
    a := [...]int{2, 3, 5, 7, 11, 13} 

    s := a[1:4] 
    fmt.Println(s)  // [3 5 7] 
    fmt.Println(len(s)) // 3 

    s = s[:4] 
    fmt.Println(s)  // [3 5 7 11] 
    fmt.Println(len(s)) // 4 

    s = a[:] 
    fmt.Println(s) // [2 3 5 7 11 13] 
}