Nannan AV
Nannan AV

Reputation: 419

Return array as interface

Case 1

I have the following method which works perfectly fine. Here I am returning an array as an interface.

func ReturnArrayAsInterface1() interface{} {
    retval := make([]int, 0)
    retval = append(retval, 4, 6, 8, 10)
    return retval
}

Case 2

Consider the following method. Here I want to return the error in case of a panic, so I define the retval at the beginning and change its value in defer. But this shows an error "Cannot use 'retval' (type interface{}) as type []Type"

func ReturnArrayAsInterface2() (retval interface{}) {
    defer func() {
        if r := recover(); r != nil {
            retval = r
        }
    }()
    retval = make([]int, 0)
    retval = append(retval, 4, 6, 8, 10) .  // error here : Cannot use 'retval' (type interface{}) as type []Type
    return retval
}

So what I would like to know is, why is it that the first function works fine whereas the second does not? Are there any ways to overcome this?

Case 3

This also works similarly to Case 2:

func ReturnArrayAsInterface3() interface{} {
    var retval interface{}
    defer func() {
        if r := recover(); r != nil {
            retval = r
        }
    }()
    retval = make([]int, 0)
    retval = append(retval, 4, 6, 8, 10) .  // error here : Cannot use 'retval' (type interface{}) as type []Type
    return retval
}

Upvotes: 3

Views: 4101

Answers (2)

dolmen
dolmen

Reputation: 8696

Case 3 will not work as in Case 2 in case of panic: in case of panic the return retval will not run, so nil will be returned by ReturnArrayAsInterface3.

To fix Case 2, use a variable with a static type as long as possible because it is safer (catches bugs) and more efficient.

func ReturnArrayAsInterface2() (retval interface{}) {
    defer func() {
        if r := recover(); r != nil {
            retval = r
        }
    }()
    r := make([]int, 0)
    retval = append(r, 4, 6, 8, 10)
    return
}

Upvotes: 1

icza
icza

Reputation: 417512

Because Go is a statically typed language. Your first example works because type of retval is []int, and so you can append int values to it. You used short variable declaration, so the type of retval is inferred from the right-hand side expression, which clearly is of type []int. When you return this []int value, it will be automatically wrapped in an interface{} value.

In your second case you use a named result type, where you explicitly specify its type to be interface{}, and you can't append values to a value of type interface{} (a non-slice type). It doesn't matter that the dynamic type of the value stored in the retval interface value is a slice, its static type is interface{}.

It would work with a type assertion:

retval = append(retval.([]int), 4, 6, 8, 10)

But the first solution is much cleaner and more efficient.

Your third case is almost like the second: you use variable declaration where you explicitly state you want the retval variable to be of type interface{}.

Upvotes: 4

Related Questions