Search code examples
pointersgocontravariance

How to change param that is interface?


The library that I'm using to work with DB provides convenient interface to save/load data without casting

Put(c context.Context, key *Key, src interface{}) (*Key, error)
Get(c context.Context, key *Key, dst interface{}) error

However, I cannot understand how GET method can possibly work. I tried to replicate behavior with the simplest snippet, but it didn't work.

import "fmt"

type MyType struct {
    inside string
}

func setVal(dst *MyType) {
    someVal := MyType{"new"}
    *dst = someVal
}

func setValGen(dst interface{}) {
    someVal := MyType{"new"}
    dst = someVal
}


func main() {
    typeDstA := MyType{"old"}
    setVal(&typeDstA)
    fmt.Println(typeDstA)     //changed to new

    typeDstB := MyType{"old"}
    setValGen(&typeDstB)
    fmt.Println(typeDstB)     //remains old
}

How they make Get function accept interface{} and change the pointer destination?


Solution

  • Most likely they are using reflection.

    https://play.golang.org/p/kU5gKjG0P8

    someVal := MyType{"new"}
    v := reflect.ValueOf(dst).Elem()
    if v.CanSet() {
        v.Set(reflect.ValueOf(someVal))
    }