Increase the cut length on the left.

I just started going through getour and ran into the question of the default chapter for slices.

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 } 

I can increase the slice length on the right by selecting an index that is greater than or equal to the previous slice length. for example s[:4] , so I can reach record 11 . But when I use s[-1:] to continue on the left and reach record 2 , the compiler gives me an invalid slice index -1 (index must be non-negative) error. Is it possible to extend the length of the fragment on the left to reach record 2 after s=s[1:4] ?

+7
go
source share
2 answers

Firstly, to answer your question, there is no way to use negative indexes or to access this data, except for saving a copy of the original fragment.

However, this is an interesting question, since there is inconsistency here that you indicated, which is probably more than what you are asking. If you start with a snippet like this :

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

[2 3 5 7 11 13] 6 6

And take a piece of just the middle

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

[3] 1 5

You are not allowed to access the indices in the source data for this len slice, as you expected:

 fmt.Println(b[3]) 

panic: runtime error: index out of range

You are not allowed to retransmit to include this data before the index starts:

 d := b[-1:] 

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

But you allowed to redistribute to include this data again after len to cap, which is a bit strange:

 // 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

This is a bit incompatible, as most other operations with slice data are limited by the offset of the data and len, and not by the cover and the original data length. However, this is explicitly stated in the specification and is probably just an artifact of how the slices represent the representation on the original array, and not an intentional design decision to provide access to this data. It would be nice if you could go back to the original repository, since it is still in memory, but it looks like you can only see the end of the array before the cap, and not the beginning after you chopped once. From spec about slicing index limits:

For arrays or strings, the indices are in the range if 0 <= low <= high <= len (a), otherwise they are out of range. For slices, the superscript bound is the capacity cap (a), not the length . The constant index must be non-negative and be represented by an int value; for arrays or constant strings, constant indexes should also be in the assortment. If both indices are constant, they must satisfy a minimum of <= high. If indexes are out of range at runtime, panic occurs at runtime.

It would probably be better to be safe and use the original slice to create different representations of the data, rather than relying on this behavior.

+1
source share

When you make a new slice from the second index in the base array, as you do with s = s[1:4] , you have lost the reference to the first element in the base array.

And since slice s[i:j] requires i >= 0 , you can no longer access the first element of the original array by slicing an existing fragment.

However, you can save the original array:

 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] } 
+6
source share

All Articles