Search code examples
gomemorymemory-managementreflectioninterface

How do you make multiple interfaces reference the same value?


I would like to make two interfaces reference the same value (meaning if you update one, the other will update to the same thing):

package main

import (
    "fmt"
    "reflect"
)

func main(){
    var a, b any

    a = "Hi"

    b = reflect.ValueOf(&a).Elem()
    a = reflect.ValueOf(&b).Elem()

    b = "Howdy"

    fmt.Println(a)
    fmt.Println(b)
}

PRINT LOGS

Howdy
Howdy

PLAYGROUND: https://go.dev/play/p/qizVO42UaUj

This code works as intended, aside from the fact that a and b are not interfaces. So when I convert them to interfaces like so...

package main

import (
    "fmt"
    "reflect"
)

func main(){
    var a, b any

    a = "Hi"

    b = reflect.ValueOf(&a).Elem().Interface()
    a = reflect.ValueOf(&b).Elem().Interface()

    b = "Howdy"

    fmt.Println(a)
    fmt.Println(b)
}

PRINT LOGS

Hi
Howdy

PLAYGROUND: https://go.dev/play/p/jCpuepBJYdD

...the code no longer works as intended.

Is there a way to use the interface data type rather than the reflect.Value data type while maintaining that the two interfaces reference the same value?


Solution

  • Simple Solution

    Figured it out—no need to use reflection. Storing the value's address in the interface will allow you to accomplish this by using a type assertion to an interface pointer and dereferencing:

    package main
    
    import "fmt"
    
    func main() {
        var object any
        object = "Hi"
    
        var a, b any
        a = &object
        b = &object
    
        *a.(*any) = "Howdy"
    
        fmt.Println(*a.(*any))
        fmt.Println(*b.(*any))
    }
    

    PRINT LOGS

    Howdy
    Howdy
    

    PLAYGROUND: https://go.dev/play/p/LEx8MR4ZK06

    Using Multiple Functions

    If you would like to abstract away the type-assertion and derefencing:

    package main
    
    import "fmt"
    
    func getStuff(a any) any {
        return *a.(*any)
    }
    
    func setStuff(a, to any) {
        *a.(*any) = to
    }
    
    func main() {
        var object any
        object = "Hi"
    
        var a, b any
        a = &object
        b = &object
    
        setStuff(a, "Howdy")
    
        fmt.Println(getStuff(a))
        fmt.Println(getStuff(b))
    }
    

    PRINT LOGS

    Howdy
    Howdy
    

    PLAYGROUND: https://go.dev/play/p/RUX4cu2Cx2o