Bill
Bill

Reputation: 25555

Go: Passing a return value via an interface{} pointer

I have a function that looks like this:

func Foo(result interface{}) error {
     ...
     json.Unmarshal([]byte(some_string), result)
     ...
}

Which is called like this:

var bar Bar
Foo(&bar)

Generally, Foo fetches a string that is then unmarshalled into the result. However, now I need to update it so that Foo sometimes loads data from another source and returns that instead.

type Loader func() (interface{})

func Foo(result interface{}, Loader load) error {
     ...
     data := load()
     // result = data ???
     ...
}

Is there any way for me to assign this new value to result? I found that I can marshal the data into a string and then unmarshal it into result which works, but I can't imagine that's the best way.

Upvotes: 2

Views: 92

Answers (1)

Aruna Herath
Aruna Herath

Reputation: 6531

You can do,

p := result.(*Bar)
*p = data

The first line is a type assertion.

The second assigns data to the dereferenced pointer. Assigning a value to a dereferenced pointer changes the value at the referenced address.

Since you don't know the underlying types of result or data the best you can do is using a type assertion switch.

switch v := data.(type) {
case Bar:
    // If 'data' is of type 'Bar'
    p, ok := result.(*Bar)
    if(!ok){
        // This means inputs were bad.
        // 'result' and 'data' should both have the same underlying type.
        fmt.Println("underlying types mismatch")
        break;
    }

    *p = v

case Baz:
    // If 'data' is of type 'Baz'
    // Equivalent of above for 'Baz'
}

See Type Switches from switch statement

Upvotes: 5

Related Questions