У меня есть немного игры с языком Движения Google, и я столкнулся с чем-то, что является довольно основным в 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]
}
}
}
Но компилятору Движения не нравится это:
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 ++/unrelated появляются для большинства критериев поиска.
Вот рабочая программа 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.
точка с запятой и звездочка добавляются и удаляются.
* y [i + j] + = x [i] * h [j]
->
(* y) [i + j] + = x [i] * h [j];
Длина является частью типа массива, вы можете получить длину массива с помощью встроенной функции 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:])
В документации Google Go говорится следующее о передаче массивов - они говорят, что вы обычно хотите передать срез ( вместо указателя?):
Как указано в комментарии @ Chickencha, фрагменты массива являются ссылками, поэтому они эффективны для передачи.Поэтому, вероятно, вы захотите использовать механизм срезов вместо «сырых» указателей.
Из Документа Google Effective Go 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 эффективно обрабатывает фрагменты. Это альтернативный ответ на вопрос, но, возможно, это лучший способ.
Типы с пустыми []
, например [] 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 с момента его первой публикации.