Source From Here
QuestionI've got this problem which seems a bit weird to me. Take a look at this snippet of code:
- package main
- import (
- "fmt"
- )
- type IterA interface{
- Filter(s *string) bool
- }
- type S1 struct {
- key string
- val string
- }
- func (so *S1) Filter(s *string) bool {
- fmt.Printf("Filter %#v\n", *so);
- return true;
- }
- type IterB interface{
- FunA(f *IterA)
- FunB(i int)
- }
- type S2 struct{
- id int
- }
- func (so *S2) FunA(f *IterA) {
- fmt.Printf("FunA by %#v\n", *so)
- }
- func (so *S2) FunB(i int) {
- fmt.Printf("FunB by %#v\n", *so)
- }
- func main(){
- fmt.Println("test");
- s1 := &S1{"key", "value"};
- data := "test"
- s1.Filter(&data)
- p_s1 := s1
- s2 := S2{1}
- s2.FunA(p_s1)
- s2.FunB(0)
- }
Why can't I pass the pointer p_s1 of S1 structure to function FunA(f *IterA) which will accept the argument as pointer of interface IterA?
HowTo
So you're confusing two concepts here. A pointer to a struct and a pointer to an interface are not the same. An interface can store either a struct directly or a pointer to a struct. In the latter case, you still just use the interface directly, not a pointer to the interface. For example:
- type Fooer interface {
- Dummy()
- }
- type Foo struct{}
- func (f Foo) Dummy() {}
- func main() {
- var f1 Foo
- var f2 *Foo = &Foo{}
- DoFoo(f1)
- DoFoo(f2)
- }
- func DoFoo(f Fooer) {
- fmt.Printf("[%T] %+v\n", f, f)
- }
In both cases, the f variable in DoFoo is just an interface, not a pointer to an interface. However, when storing f2, the interface holds a pointer to a Foo structure.
Pointers to interfaces are almost never useful. In fact, the Go runtime was specifically changed a few versions back to no longer automatically dereference interface pointers (like it does for structure pointers), to discourage their use. In the overwhelming majority of cases, a pointer to an interface reflects a misunderstanding of how interfaces are supposed to work.
However, there is a limitation on interfaces. If you pass a structure directly into an interface, only value methods of that type (ie. func (f Foo) Dummy(), not func (f *Foo) Dummy()) can be used to fulfill the interface. This is because you're storing a copy of the original structure in the interface, so pointer methods would have unexpected effects (ie. unable to alter the original structure). Thus the default rule of thumb is to store pointers to structures in interfaces, unless there's a compelling reason not to.
Specifically with your code, if you change the FunA function signature to:
- func (so *S2) FunA(f IterA)
* Medium - Interfaces in Go
* The Go Blog - The Laws of Reflection
沒有留言:
張貼留言