我正在玩google的Go语言,我遇到了一些在C中相当基本的东西,但是到目前为止我看到的文档中似乎没有涉及
当我将指向切片的指针传递给函数时,我假设我们可以通过以下方式访问它:
func conv(x []int, xlen int, h []int, hlen int, y *[]int)
for i := 0; i<xlen; i++ {
for j := 0; j<hlen; j++ {
*y[i+j] += x[i]*h[j]
}
}
}
但Go编译器不喜欢这样:
sean@spray:~/dev$ 8g broke.go
broke.go:8: invalid operation: y[i + j] (index of type *[]int)
足够公平 - 这只是猜测。我有一个相当简单的解决方法:
func conv(x []int, xlen int, h []int, hlen int, y_ *[]int) {
y := *y_
for i := 0; i<xlen; i++ {
for j := 0; j<hlen; j++ {
y[i+j] += x[i]*h[j]
}
}
}
但肯定有更好的方法。令人讨厌的是,在Google上搜索信息并不是很有用,因为大多数搜索字词会显示各种C / C ++ /无关结果。
答案 0 :(得分:25)
Google Go文档state the following about passing arrays - 他们说您通常想要传递切片(而不是指针?):
如@ Chickencha的评论所示,数组切片是参考,这就是为什么它们有效传递的原因。因此,您可能希望使用切片机制而不是“原始”指针。
来自 Google Effective Go doc http://golang.org/doc/effective_go.html#slices
切片是参考类型,
它位于标题下
关于类型的插曲
[... snip ...]传递数组时 一个功能,你几乎总是想要 声明形式参数 一片。当你调用这个函数时 取数组的地址和Go 将创建(有效)切片 参考并通过它。
编者注:不再是这种情况
使用切片可以编写此函数(来自sum.go):
09 func sum(a []int) int { // returns an int
10 s := 0
11 for i := 0; i < len(a); i++ {
12 s += a[i]
13 }
14 return s
15 }
并像这样调用它:
19 s := sum(&[3]int{1,2,3}) // a slice of the array is passed to sum
也许将整个数组作为切片传递。谷歌通过切片有效地表明Go交易。这是问题的替代答案,但也许这是一种更好的方式。
答案 1 :(得分:14)
空[]
的类型,例如[]int
实际上是切片,而不是数组。在Go中,数组的大小是类型的一部分,因此要实际拥有一个数组,您需要具有[16]int
之类的内容,并且指向该数组的指针将为*[16]int
。所以,你实际上已经在做的是使用切片,并且指向切片的指针*[]int
是不必要的,因为切片已经通过引用传递。
还要记住,您可以使用(不再是。)&array
轻松传递引用整个数组的切片(只要切片的元素类型与数组的元素类型匹配)。
示例:
package main
import "fmt"
func sumPointerToArray(a *[8]int) (sum int) {
for _, value := range *a { sum += value }
return
}
func sumSlice (a []int) (sum int) {
for _, value := range a { sum += value }
return
}
func main() {
array := [...]int{ 1, 2, 3, 4, 5, 6, 7, 8 }
slice := []int{ 1, 2, 3, 4 }
fmt.Printf("sum arrray via pointer: %d\n", sumPointerToArray(&array))
fmt.Printf("sum slice: %d\n", sumSlice(slice))
slice = array[0:]
fmt.Printf("sum array as slice: %d\n", sumSlice(slice))
}
修改:已更新,以反映自首次发布以来Go中的更改。
答案 2 :(得分:5)
添加并删除分号和星号。
* y [i + j] + = x [i] * h [j]
- &GT;
(* y)[i + j] + = x [i] * h [j];
答案 3 :(得分:2)
长度是数组类型的一部分,您可以通过len()内置函数获取数组的长度。所以你不需要传递xlen,hlen参数。
在Go中,将数组传递给函数时几乎总能使用切片。在这种情况下,您不需要指针。 实际上,你不需要传递y参数。这是C的输出数组的方式。
在Go风格中:
func conv(x, h []int) []int {
y := make([]int, len(x)+len(h))
for i, v := range x {
for j, u := range h {
y[i+j] = v * u
}
}
return y
}
调用该函数:
conv(x[0:], h[0:])
答案 4 :(得分:2)
这是一个有效的Go程序。
package main
import "fmt"
func conv(x, h []int) []int {
y := make([]int, len(x)+len(h)-1)
for i := 0; i < len(x); i++ {
for j := 0; j < len(h); j++ {
y[i+j] += x[i] * h[j]
}
}
return y
}
func main() {
x := []int{1, 2}
h := []int{7, 8, 9}
y := conv(x, h)
fmt.Println(len(y), y)
}
为避免错误的猜测,请阅读Go文档:The Go Programming Language.