0

In the next code the first Println fails on build with error slice of unaddressable value. The rest of the lines are just fine.

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[:])
}

Try this code

If the first Println is commented it works. Try it out

Why is that? What I'm missing here?

icza
  • 389,944
  • 63
  • 907
  • 827
edupo
  • 188
  • 1
  • 7

2 Answers2

5

What you're missing is that when slicing an array, the operand must be addressable ([0]int is an array, not a slice). And return values of function calls are not addressable. For details see How can I store reference to the result of an operation in Go?; and "cannot take the address of" and "cannot call pointer method on".

Spec: Slice expressions:

If the sliced operand is an array, it must be addressable and the result of the slice operation is a slice with the same element type as the array.

In this expression:

getSlice()[:]

getSlice() returns an array, and since it's the result of a function call, it's not addressable. Therefore you cannot slice it.

In this expression:

getString()[:]

getString() returns a string value, so it can be sliced even if the value is not addressable. This is allowed, because the result of the slice expression will be another string, and string values in Go are immutable.

Also, variables are addressable, so this will always work:

var a = getSlice()
fmt.Println(a[:])
icza
  • 389,944
  • 63
  • 907
  • 827
  • I still did not understand why `getString()[:]` would work. – naneri Apr 17 '23 at 16:11
  • @naneri Because the operand in the slicing expression only needs to be addressable if it's an array, but not if it's a `string`. – icza Apr 17 '23 at 17:21
1

getSlice() is not returning a slice it's returning an array, which is not addressable. You could return a pointer to the array:

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

or leave getSlice() as is and place the result in a temporary variable:

t := getSlice()
fmt.Println(t[:])
GilesW
  • 485
  • 2
  • 7