doujian1954 2013-09-04 16:23
浏览 52

如何在Go中的指针到指针上键入选择接口?

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
", 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?

  • 写回答

2条回答 默认 最新

  • dsy19890123 2013-09-04 16:26
    关注

    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()
    }
    

    Playground


    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.

    评论

报告相同问题?

悬赏问题

  • ¥500 火焰左右视图、视差(基于双目相机)
  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本