Reputation: 22592
I have a pair of interfaces defined like so:
type Marshaler interface {
Marshal() ([]byte, error)
}
type Unmarshaler interface {
Unmarshal([]byte) error
}
I have a simple type which implement these:
type Foo struct{}
func (f *Foo) Marshal() ([]byte, error) {
return json.Marshal(f)
}
func (f *Foo) Unmarshal(data []byte) error {
return json.Unmarshal(data, &f)
}
I am using a library which defines a different interface, and implementing it like so:
func FromDb(target interface{}) { ... }
The value being passed for target
is a pointer to pointer:
fmt.Println("%T\n", target) // Prints **main.Foo
Typically this function does a type switch and then operates on the type underneath. I would like to have common code for all types that implement my Unmarshaler
interface but can't figure out how to get from a pointer-to-pointer of a specific type to my interface.
You cannot define methods on a pointer to a pointer:
func (f **Foo) Unmarshal(data []byte) error {
return json.Unmarshal(data, f)
}
// compile error: invalid receiver type **Foo (*Foo is an unnamed type)
You cannot define receiver methods on pointer types:
type FooPtr *Foo
func (f *FooPtr) Unmarshal(data []byte) error {
return json.Unmarshal(data, f)
}
// compile error: invalid receiver type FooPtr (FooPtr is a pointer type)
Casting to Unmarshaler
doesn't work:
x := target.(Unmarshaler)
// panic: interface conversion: **main.Foo is not main.Unmarshaler: missing method Unmarshal
Casting to *Unmarshaler
doesn't work either:
x := target.(*Unmarshaler)
// panic: interface conversion: interface is **main.Foo, not *main.Unmarshaler
How can I get from this pointer-to-pointer type to my interface type without needing to switch on every possible implementor type?
Upvotes: 3
Views: 1190
Reputation: 22991
If target
is a **Foo
and *Foo
implements Unmarshaler
, you can do:
var x Unmarshaler = *target
If target is a an interface{}
containing a **Foo
, this would work instead:
var x Unmarshaler = *(target.(**Foo))
It's a similar idea if you have a type switch.
Whenever I have to deal with pointer-to-pointer or pointer-to-reference, the variable life-time is generally pretty short and they quickly go back to being a single pointer (or plain reference) again.
I'd evaluate whether the pointer-to-pointer is indeed required for the use case at hand or whether you can do something like that.
Upvotes: 2
Reputation: 91203
It's ugly, but is is possible to have the semantic equivalent of a pointer to pointer receiver. For example:
package main
import "fmt"
type P *int
type W struct{ p P }
func (w *W) foo() {
fmt.Println(*w.p)
}
func main() {
var p P = new(int)
*p = 42
w := W{p}
w.foo()
}
Output:
42
Note that
fmt.Println(*w.p)
above is actually
fmt.Println(*(*w).p)
where the extra work is done for you by the compiler automagically.
Upvotes: 3