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.

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

报告相同问题?

悬赏问题

  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀
  • ¥20 手写数字识别运行c仿真时,程序报错错误代码sim211-100