使用指向数组的指针

时间:2010-03-13 18:24:39

标签: pointers go

我正在玩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 ++ /无关结果。

5 个答案:

答案 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.