Использование указателя на массив
У меня небольшая игра с языком 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 это не нравится:
[email protected]:~/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 для Go не очень полезен, поскольку для большинства поисковых запросов появляются всевозможные C/С++/несвязанные результаты.
Ответы
Ответ 1
Документы Google Go сообщают следующее о передаче массивов - говорят, что вы обычно хотите передать срез (вместо указатель):
Обновлено:
Как указано комментарием @Chickencha, срезы массива являются ссылками, поэтому они эффективны для прохождения. Вероятно, вы захотите использовать механизм среза вместо "сырых" указателей.
От Эффективный документ Google 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
Возможно, передайте весь массив как срез. Google указывает, что Go работает эффективно с помощью срезов. Это альтернативный ответ на вопрос, но, возможно, это лучший способ.
Ответ 2
Типы с пустым []
, такие как []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, поскольку это было впервые опубликовано.
Ответ 3
точка с запятой и звездочка добавляются и удаляются.
* y [i + j] + = x [i] * h [j]
- >
(* y) [i + j] + = x [i] * h [j];
Ответ 4
Длина является частью типа массива, вы можете получить длину массива с помощью встроенной функции 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:])
Ответ 5
Здесь работает рабочая программа 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: Язык программирования Go.