切片作为参数传递的切片指针
Slicing a slice pointer passed as argument
我有以下代码:
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:]
}
它给我一个错误,我不能在 sliceArr()
函数的参数中使用类型 []byte
作为类型 *[]byte
,并且我不能切片类型 *[]byte
。怎么了?默认情况下不是通过引用传递切片吗?我试图在没有指针的情况下执行此操作,但它不起作用 - 正在复制数组。我该怎么做?
错误 cannot use type []byte as type *[]byte in argument to sliceArr()
来自您未发布的拼写错误(您试图传递切片而不是指向切片的指针 sliceArr()
)。
至于另一个错误(cannot slice type *[]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]
是 shorthand (*p)[low:high]
,即自动为你解引用指针。如果 p
是指向 slice 的指针,这不会自动发生,p[low:high]
无效,因为您不能对指针进行切片。因此,如果指针指向切片,您必须手动取消引用指针。
出现这种偏差的原因是指向切片的指针非常罕见,因为切片已经是 "just" 描述符(指向底层数组的连续部分),并且切片在大多数情况下都没有指针传递时间,所以如果在极少数情况下(比如这个)你确实需要传递一个指针,你需要明确地处理它。另一方面,数组代表所有元素;分配或传递数组会复制所有值,因此使用指向数组的指针(而不是指向切片的指针)更为常见 - 因此有更多语言支持使用数组指针是合理的。
另请注意,您的任务可以通过只需要一个(非指针)切片作为参数类型并返回新的切片值来实现 - 当然必须在调用者处分配(一个很好的例子是内置 append()
函数)。
注释 #2:
如果参数类型是切片(而不是指向切片的指针),并且您传递一个切片,则不会复制底层数组,只会复制切片 header。但在这种情况下,如果您对参数进行切片(切片 header 的副本),并将新切片(切片 header)分配回参数,您只是更改了值参数(局部变量)而不是传递的原始值(变量),这就是它不起作用的原因。
阅读以下博客文章以了解有关切片的更多详细信息:
我有以下代码:
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:]
}
它给我一个错误,我不能在 sliceArr()
函数的参数中使用类型 []byte
作为类型 *[]byte
,并且我不能切片类型 *[]byte
。怎么了?默认情况下不是通过引用传递切片吗?我试图在没有指针的情况下执行此操作,但它不起作用 - 正在复制数组。我该怎么做?
错误 cannot use type []byte as type *[]byte in argument to sliceArr()
来自您未发布的拼写错误(您试图传递切片而不是指向切片的指针 sliceArr()
)。
至于另一个错误(cannot slice type *[]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]
是 shorthand (*p)[low:high]
,即自动为你解引用指针。如果 p
是指向 slice 的指针,这不会自动发生,p[low:high]
无效,因为您不能对指针进行切片。因此,如果指针指向切片,您必须手动取消引用指针。
出现这种偏差的原因是指向切片的指针非常罕见,因为切片已经是 "just" 描述符(指向底层数组的连续部分),并且切片在大多数情况下都没有指针传递时间,所以如果在极少数情况下(比如这个)你确实需要传递一个指针,你需要明确地处理它。另一方面,数组代表所有元素;分配或传递数组会复制所有值,因此使用指向数组的指针(而不是指向切片的指针)更为常见 - 因此有更多语言支持使用数组指针是合理的。
另请注意,您的任务可以通过只需要一个(非指针)切片作为参数类型并返回新的切片值来实现 - 当然必须在调用者处分配(一个很好的例子是内置 append()
函数)。
注释 #2:
如果参数类型是切片(而不是指向切片的指针),并且您传递一个切片,则不会复制底层数组,只会复制切片 header。但在这种情况下,如果您对参数进行切片(切片 header 的副本),并将新切片(切片 header)分配回参数,您只是更改了值参数(局部变量)而不是传递的原始值(变量),这就是它不起作用的原因。
阅读以下博客文章以了解有关切片的更多详细信息: