Pointers 如何获取接口{}的指针以检查接口实现的类型

Pointers 如何获取接口{}的指针以检查接口实现的类型,pointers,go,interface,Pointers,Go,Interface,所以我基本上是想找出最好的方法来达到这样的目的: package main import "fmt" type SomeStruct struct { } type SomeInterface interface { SomeMethodWhichNeedsAPointerReceiver() string } func (s *SomeStruct) SomeMethodWhichNeedsAPointerReceiver() string { return "Well, be

所以我基本上是想找出最好的方法来达到这样的目的:

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方法中的typecast。 我基本上只知道它是接口{}类型,现在我需要 调用具有指针接收器的接口方法

目前我唯一的解决方案是动态构造一个带有反射的切片,将元素设置到切片中,然后使其可寻址

这真的是找到解决办法的唯一可能性吗


在Go中,接口只是一组方法()

接口不指定接收器是否为指针。在Go中实现接口是隐式的:没有意图声明

你需要阅读和理解。引用其中一个重要部分:

任何其他类型
T
的方法集都由使用接收方类型
T
声明的所有方法组成。相应的
*T
的方法集是与接收方
*T
T
声明的所有方法集(也就是说,它还包含
T
的方法集)

如果其类型的方法集是接口(接口类型的方法)的超集,则值(可能是指针也可能不是指针)实现接口

在您的示例中:

func (s *SomeStruct) SomeMethodWhichNeedsAPointerReceiver() string{}
SomeMethodWhichNeedsAPointerReceiver()
具有指针接收器,因此类型为
SomeStruct
的值将不具有此方法,而类型为
*SomeStruct
的值将具有此方法

因此,类型为
SomeStruct
的值不会实现
SomeInterface
接口(因为它没有
SomeMethodWhichNeedsAPointerReceiver()
方法),但是
*SomeStruct
确实实现了
SomeInterface
,因为它的方法集包含
SomeMethodWhichNeedsAPointerReceiver()
方法

由于您创建并使用了一个简单的
SomeStruct
值(而不是指向它的指针),因此类型断言将失败

如果您使用了
*SomeStruct
,那么类型断言就会成功

修改您的
SomeThirdPartyMethod()
函数以创建并返回
*SomeStruct
(指针),它将按照您的预期工作:

func SomeThirdPartyMethod() interface{} {
    return &SomeStruct{}
}
或者作为替代方案:

func SomeThirdPartyMethod() interface{} {
    return new(SomeStruct)
}
试穿一下

如果无法修改
SomeThirdPartyMethod()
如果无法修改
SomeThirdPartyMethod()
函数:首先,它是否打算/需要返回一个实现
SomeStruct
的值?如果是这样,那么它的当前实现是错误的,您可以期望它返回一个实现
SomeStruct
的值,而不必取消引用它(以便获得实现
SomeStruct
的值)

在此特定情况下,您还可以尝试对
SomeStruct
本身进行类型断言:

if ss, ok := s.(SomeStruct); ok {
    fmt.Println(ss.SomeMethodWhichNeedsAPointerReceiver())
}

调用
ss.SomeMethodWhichNeedsAPointerReceiver()
将自动取消引用
ss
以获取其地址(这将是调用
SomeMethodWhichNeedsAPointerReceiver()
方法的指针接收器值).

最好的解决方案确实是从
第三方方法
返回指针。但如果不可能,可以使用以下方法构造指向该值的指针:


工作示例:

井的可能重复并非真的,因为我实际上想要一个没有反射的解决方案。但是,是的,如果不可能的话,它可能是重复的。对我来说,我不喜欢第三方libs,它有funcs返回接口{}。在我看来,它没有类型,很难理解和使用,不好的实践。我只是避免使用这样的库。我更喜欢显式返回某些内容的SomeThirdPartyMethod(),比如SomeStruct或SomeInterface,但不是interface{}。如果返回类型为interface,则是相同的,比如。。。接口A和它可以选择性地实现接口B。好的,第三方方法将接口指定为可选的。因此,它不能被实现,返回值是接口{}。这并不优雅,但事实就是如此。是的,这也是我们找到的唯一方法。我对你的答案投了赞成票,但我现在就让这个问题公开讨论,以寻求其他建议。但对于您目前的回复,请点击thx:D
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
}