drls2738 2014-01-01 04:30
浏览 24
已采纳

指向接口的指针有意义吗?

This code does not compile - type *IF does not have method MyMethod:

  1 package main
  2 
  3 type IF interface {
  4     MyMethod(i int)
  5 }
  6 
  7 type AType struct {
  8     I *IF
  9 }
 10 
 11 func (a *AType) aFunc() {
 12     a.I.MyMethod(1)
 13 }

However, it compiles OK if I is defined as an IF itself:

  1 package main
  2 
  3 type IF interface {
  4     MyMethod(i int)
  5 }
  6 
  7 type AType struct {
  8     I IF          // not a pointer
  9 }
 10 
 11 func (a *AType) aFunc() {
 12     a.I.MyMethod(1)
 13 }

In my case, the I should be pointer to a record that implements IF, but why is it not allowed?

  • 写回答

1条回答 默认 最新

  • douqun1977 2014-01-01 06:48
    关注

    In my case, the I should be pointer to a record that implements IF, but why is it not allowed?

    If this is your goal, you're going about it incorrectly. An interface is a wrapper, and a contract that guarantees behavior. If your interface requires that the methods mutate the implementing type, then the implementing type should be a pointer. A pointer to the interface itself will not suddenly make the implementing type mutable.

    Think of it this way, if I have a struct like this:

    type A struct {
        b MyType
    }
    
    type A2 struct {
        b *MyType
    }
    
    mt := MyType{/* initialization stuff */}
    a := &A{mt}
    a2 := A2{&mt}
    

    Then a and a2 are not equivalent. If I want a pointer to mt, then I should use A2, not A. Even if I try my hardest and do stuff like &a.b, it will never be a pointer to the original mt. Think of an interface the same way, but where b is the type implementing the interface. What you're trying to do with I is equivalent to taking &A{} and attempting to use it as a pointer to mt, when you should be using A2.

    When you have

    func (mt MyType) MyMethod(i int) {
    
    }
    

    Then that interface will never hold anything other than a copy of mt. If you want a "pointer to the record" you must implement

    func (mt *MyType) MyMethod(i int) {
    
    }
    

    This is equivalent to the difference between A and A2 above, you'll simply never be able to get a pointer to the original object if you use the first implementation.

    As for why, exactly, you can't call methods on a pointer to an interface without explicitly dereferencing it despite Go typically having transparent pointers, I'm not clear on the rationale. However, if you really still want a pointer to the interface-wrapper, calling MyMethod(1) should work as (*a.I).MyMethod(1) in the pointer implementation. Just be aware that this won't alter the behavior of the code at all if the implementer of IF is a naked type and not a pointer to a type.

    Now for the final question: why is there no construct similar to "a pointer to a naked type that implements this interface"? The reason, to the best of my intuition, is that an interface is about behavior, not data. What would you do with such a pointer? The methods will still be called on the naked type despite having a pointer, and you don't have access to any of its fields since they're not exposed by the interface. You also couldn't write to the location pointed to because the the types may not match. It would be a mostly useless construct.

    You could probably get an equivalent assertion to "is this a pointer to data that implements my interface?" by using reflection, but in most cases it likely wouldn't be a very interesting or useful thing to know.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥30 vmware exsi重置后的密码
  • ¥15 易盾点选的cb参数怎么解啊
  • ¥15 MATLAB运行显示错误,如何解决?
  • ¥15 c++头文件不能识别CDialog
  • ¥15 Excel发现不可读取的内容
  • ¥15 关于#stm32#的问题:CANOpen的PDO同步传输问题
  • ¥20 yolov5自定义Prune报错,如何解决?
  • ¥15 电磁场的matlab仿真
  • ¥15 mars2d在vue3中的引入问题
  • ¥50 h5唤醒支付宝并跳转至向小荷包转账界面