Ошибка при адресации возвращенного фрагмента функции - PullRequest
0 голосов
/ 27 апреля 2018

В следующем коде первый Println завершается неудачно при сборке с ошибкой slice of unaddressable value. Остальные строки просто в порядке.

package main

import "fmt"

func getSlice() [0]int {
   return [...]int{}
}

func getString() string {
   return "hola"
}

func main() {
    fmt.Println(getSlice()[:]) // Error: slice of unaddressable value

    var a = getSlice()
    fmt.Println(a[:])

    fmt.Println(getString()[:])

    var b = getString()
    fmt.Println(b[:])
}

Попробуйте этот код

Если первый Println прокомментирован, это работает. Попробуй

Почему это? Что мне здесь не хватает?

Ответы [ 2 ]

0 голосов
/ 27 апреля 2018

getSlice() не возвращает срез, а возвращает массив, который не адресуется. Вы можете вернуть указатель на массив:

func getSlice() *[0]int {
   return &[...]int{}
}

или оставьте getSlice() как есть и поместите результат во временную переменную:

t := getSlice()
fmt.Println(t[:])
0 голосов
/ 27 апреля 2018

Что вам не хватает, так это то, что при нарезке массива операнд должен быть адресуемым ([0]int - это массив, а не срез). И возвращаемые значения вызовов функций не адресуемы. Подробнее см. Как сохранить ссылку на результат операции в Go? ; и "не может получить адрес" и "не может вызвать метод указателя на" .

Spec: выражения среза:

Если нарезанный операнд является массивом, он должен быть адресуемым , а результатом операции среза будет срез с тем же типом элемента, что и массив.

В этом выражении:

getSlice()[:]

getSlice() возвращает массив , и, поскольку он является результатом вызова функции, он не адресуется. Поэтому вы не можете нарезать его.

В этом выражении:

getString()[:]

getString() возвращает значение string, поэтому его можно разрезать, даже если это значение не адресуемое. Это разрешено, потому что результатом выражения среза будет другое string, а значения string в Go являются неизменяемыми.

Кроме того, переменные адресуемые , так что это всегда будет работать:

var a = getSlice()
fmt.Println(a[:])
...