切片作为参数传递的切片指针 [英] Slicing a slice pointer passed as argument

查看:185
本文介绍了切片作为参数传递的切片指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  func main(){
var buf [] byte {1, 2,3,4,5}
buf = buf [2:]
fmt.Println(buf)
panic(1)
}
buf
字节片段的指针到另一个函数,并且



>切片它在那里,所以像这样:

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

func sliceArr(buf * [] byte,i int){
* buf = * buf [i:]
}

它给我一个错误,我不能使用类型 [] byte 作为类型 * [] byte sliceArr()函数的参数中,并且我不能切分类型 * [] byte 。怎么了?默认情况下是不是通过引用传递片段?我试图做到这一点没有指针,但它不起作用 - 数组正在被复制。

()的参数中的字节来自您尚未发布的错字(您试图传递片段而不是指向 slice的片段的指针sliceArr()

至于另一个错误(不能分片类型* [] byte ),你只需要用圆括号来分组指针:

  * buf =(* buf)[i:] 

你不小心遗漏了变量中的 = 符号宣言。除此之外,一切都按照你写的方式工作:

  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:]
}

输出(在 Go Playground 上试用):

  [3 4 5] 

注意: specification states ,如果 p 是指向数组的指针, p [low:high] (* p)[low:high] 的缩写,也就是说,指针自动为您取消引用。如果 p 是一个指向切片的指针, p [low:high] 无效,因为您无法切分指针。所以你必须手动取消引用指针,以防指向切片。



这个偏差的原因是指向切片的指针非常罕见,因为切片已经是仅仅描述符(对底层数组的连续部分),并且切片大部分时间都没有指针传递,所以如果在极少数情况下(比如这个)你需要传递一个指针,你需要明确地处理它。另一方面,数组代表所有元素;赋值或传递数组拷贝所有的值,所以使用指向数组的指针(比指向切片的指针)更为常见 - 因此,使用数组指针有更多的语言支持是合理的。



还要注意你的任务可以通过只需要一个(非指针)片作为参数类型并返回新的片值来实现 - 当然这必须在调用者处分配(这是一个很好的例子是内置的 append() 函数)。
$ b

注意#2:

如果参数类型是切片(而不是指向片的指针),并且传递片,底层数组不会被复制,只有片头。但是在这种情况下,如果你切片参数(它是切片标题的一个副本),并且你将新切片(切片标题)分配给参数,你只需要改变参数的值(一个局部变量)和而不是传递的原始值(变量),这就是为什么它不起作用。



阅读以下博客文章以获取有关切片的更多详细信息:



开始切片:使用和内部结构

a>



数组,片段(和字符串):力学'append'


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 want to pass a pointer to buf byte slice to another function, and slice it there, so something like:

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

func sliceArr(buf *[]byte, i int) {
    *buf = *buf[i:]
}

It gives me an error that I cannot use type []byte as type *[]byte in argument to sliceArr() function, and that I cannot slice type *[]byte. What's wrong? Aren't slices passed by reference by default? I tried to do this without a pointer but it doesn't work - the array is being copied. How can I do this?

解决方案

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'

这篇关于切片作为参数传递的切片指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆