所以我基本上试图找到达到这样的最好方法:
package main
import "fmt"
type SomeStruct struct {
}
type SomeInterface interface {
SomeMethodWhichNeedsAPointerReceiver() string
}
func (s *SomeStruct) SomeMethodWhichNeedsAPointerReceiver() string {
return "Well, believe me, I wrote something"
}
func Run(s interface{}) {
// how can I cast s to a pointer here?
casted, ok := (s).(SomeInterface)
if ok {
fmt.Println("Awesome: " + casted.SomeMethodWhichNeedsAPointerReceiver())
return
}
fmt.Println("Fail :(")
}
func SomeThirdPartyMethod() interface{} {
return SomeStruct{}
}
func main() {
x := SomeThirdPartyMethod()
Run(x)
}
我的问题是,在Run方法的类型转换中。 我基本上只知道它是interface {}类型,现在我需要 调用一个接口方法,它有一个指针接收器。
我目前唯一的解决方案是使用反射动态构造切片,将元素设置为切片,然后使其可以进行处理。
这真的是找到解决方案的唯一可能性吗?
答案 0 :(得分:6)
在Go中,界面只是一组方法(spec: Interface types)。
接口未指定接收器是否为指针。在Go中实现接口是隐含的:没有意图声明。
您需要阅读并理解Method sets。引用其中的一个重要部分:
任何其他类型
T
的方法集由声明为接收器类型T
的所有methods组成。相应pointer type*T
的方法集是使用receiver*T
或T
声明的所有方法的集合(也就是说,它还包含{{1}的方法集}})。
值(可能是也可能不是指针)如果其类型的方法集是接口的超集(接口类型的方法),则实现接口。
在你的例子中:
T
func (s *SomeStruct) SomeMethodWhichNeedsAPointerReceiver() string{}
有一个指针接收器,因此类型为SomeMethodWhichNeedsAPointerReceiver()
的值不会有此方法,但类型为SomeStruct
的值将为。
因此,*SomeStruct
类型的值不会实现您的SomeStruct
接口(因为它没有SomeInterface
方法),但{ {1}} 确实实施您的SomeMethodWhichNeedsAPointerReceiver()
,因为其方法集包含*SomeStruct
方法。
由于您创建并使用简单的SomeInterface
值(而不是指向它的指针),因此类型断言将失败。
如果你使用了SomeMethodWhichNeedsAPointerReceiver()
,那么类型断言就会成功。
修改您的SomeStruct
函数以创建并返回*SomeStruct
(指针),它将按预期工作:
SomeThirdPartyMethod()
或作为替代方案:
*SomeStruct
在Go Playground上尝试。
func SomeThirdPartyMethod() interface{} {
return &SomeStruct{}
}
如果你不能修改func SomeThirdPartyMethod() interface{} {
return new(SomeStruct)
}
函数:首先,它是否打算/要求它返回一个实现SomeThirdPartyMethod()
的值?如果是这样,那么它的当前实现是错误的,你可以期望它返回一个实现SomeThirdPartyMethod()
的值,而不必取消引用它(为了获得实现SomeStruct
的值)。 / p>
在这种特定情况下,您还可以尝试为SomeStruct
本身输入断言:
SomeStruct
调用SomeStruct
将自动取消引用if ss, ok := s.(SomeStruct); ok {
fmt.Println(ss.SomeMethodWhichNeedsAPointerReceiver())
}
以获取其地址(这将是用于调用ss.SomeMethodWhichNeedsAPointerReceiver()
方法的指针接收器值。)
答案 1 :(得分:4)
最好的解决方案确实是从SomeThirdPartyMethod
返回一个指针。但如果无法做到这一点,您可以使用reflection构建指向该值的指针:
v := reflect.Indirect(reflect.New(reflect.TypeOf(s)))
v.Set(reflect.ValueOf(s))
sp := v.Addr().Interface()
casted, ok = (sp).(SomeInterface)
if ok {
fmt.Println("Good as well: " + casted.SomeMethodWhichNeedsAPointerReceiver())
return
}