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.