簡體   English   中英

去切片-[:n]和[n:]之間的區別

[英]Go Slice - difference between [:n] and [n:]

轉到“切片”問題,請檢查以下內容,並在我遺漏某些東西時發表評論。

   import "fmt"
   func main() {
       s := []int{2, 3, 5, 7, 11, 13}
       s = s[1:]
       fmt.Println(s)
       s = s[2:]
       fmt.Println(s)
       s = s[5:]
       fmt.Println(s)
  }

輸出:

[3 5 7 11 13] [7 11 13] panic: runtime error: slice bounds out of range

以上是合理的。

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

輸出:

[2] [2 3] [2 3 5 7 11]

這是否也應該使數組擺脫s = s [:2]的恐慌?

Go中的分片允許您在分片的末尾進行分片,只要它仍在底層陣列的容量范圍內即可。 您不能該切片的開始之前進行切片,但是只要不超過最后分配的索引,就可以在該切片之后進行切片。

舉個例子, s[3:]然后s[:3]有效,但是s[4:]然后s[:4]會恐慌,因為您請求的是底層數組的索引4到7索引0-5。

這有點奇怪,但是它確實允許您通過執行slice = slice[:cap(slice)]來最大化任何切片。

https://play.golang.org/p/Gq5xoXc3Vd

語言規范對此進行了說明,順便說一句。 我在下面對您使用的簡單切片符號進行了解釋(有一種替代方法也為新切片指定了最大索引)。

對於字符串,數組,指向數組或切片a的指針,主表達式a[low : high]構造一個子字符串或切片。 如果0 <=低<=高<= cap(a),則索引在范圍內,否則它們超出范圍。

在閱讀官方博客后,我只是想分享我的想法: https : //blog.golang.org/slices

這是Golang博客中的sliceHeader:

type sliceHeader struct {
    Length        int
    ZerothElement *byte
}

現在,您聲明您的切片:

s := []int{2, 3, 5, 7, 11, 13}

我相信這樣做:

var array [6]int
slice := sliceHeader {
    Length:        6,
    ZerothElement: &array[0], 
}

通過執行: s = s[:2] ,您有效地將sliceHeader的Length從6更改為2,因此sliceHeader將如下所示:

slice := sliceHeader {
    Length:        2,
    ZerothElement: &array[0],
}

請注意,ZerothElement仍指向內存中的同一位置。 因此,我們可以通過簡單地再次更改Length來將切片擴展回其原始形式s = s[:6]

現在,假設您沒有執行s = s[:2] ,而是執行了s = s[2:] ,您實際上所做的是通過從Length中減去2並向前移動ZerothElement兩個索引來隱藏前兩個元素,導致sliceHeader為:

slice := sliceHeader {
    Length:        4,
    ZerothElement: &array[2],   
}

此時,您無法將切片恢復為原始形式,因為無法將切片擴展到ZerothElement之外。 好吧,如果假設您可以訪問ZerothElement之前的任何元素,該怎么辦? 然后我們的切片變為未定義,因為它可能是array[0...4]array[1...5]array[2...6]

是的,這就是為什么我認為[n:]和[:n]表現不同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM