Slicing a slice pointer passed as argument

后端 未结 1 1185
南笙
南笙 2020-11-28 14:40

I have the following code:

func main() {
    var buf []byte{1, 2, 3, 4, 5}
    buf = buf[2:]
    fmt.Println(buf)
    panic(1)
}

However I

相关标签:
1条回答
  • 2020-11-28 15:18

    The error cannot use type []byte as type *[]byte in argument to sliceArr() comes from a typo which you haven't posted (you tried to pass a slice and not a pointer to a slice to sliceArr()).

    As to the other error (cannot slice type *[]byte), you just need to use parenthesis to group the pointer dereferencing:

    *buf = (*buf)[i:]
    

    And you accidentally left out a = sign from the variable declaration. Other than that, everything works as you wrote it:

    func main() {
        var buf = []byte{1, 2, 3, 4, 5}
        sliceArr(&buf, 2)
        fmt.Println(buf)
    }
    
    func sliceArr(buf *[]byte, i int) {
        *buf = (*buf)[i:]
    }
    

    Output (try it on the Go Playground):

    [3 4 5]
    

    Note:

    Note that the specification states that if p is a pointer to an array, p[low:high] is shorthand for (*p)[low:high], that is, the pointer is dereferenced automatically for you. This does not happen automatically if p is a pointer to a slice, p[low:high] is invalid as you cannot slice a pointer. So you have to dereference the pointer manually in case of pointers to slices.

    Reason for this deviation is that a pointer to a slice is very rare as slices are already "just" descriptors (to a contiguous part of an underlying array), and slices are passed without a pointer most of the time, so if in the rare case (like this one) you do need to pass a pointer, you need to be explicit about handling it. Arrays on the other hand represent all the elements; assigning or passing arrays copies all the values, so it is much more common to use pointers to arrays (than pointers to slices) - hence it is justified to have more language support for working with array pointers.

    Also note that your task could be achieved by requiring only a (non pointer) slice as the parameter type and returning the new slice value - which of course must be assigned at the caller (a good example for this is the builtin append() function).

    Note #2:

    If the parameter type is a slice (and not a pointer to a slice), and you pass a slice, the underlying array is not copied, only the slice header. But in this case if you slice the argument (which is a copy of the slice header), and you assign back the new slice (slice header) to the argument, you are just changing the value of the parameter (a local variable) and not the original value (variable) that was passed, this is why it won't work.

    Read the following blog posts for more details on slices:

    Go Slices: usage and internals

    Arrays, slices (and strings): The mechanics of 'append'

    0 讨论(0)
提交回复
热议问题