不,我不认为这是重复的 How to determine an interface{} value's "real" type?。我知道如何获取接口变量的类型,但是我无法找到一种方法来获取指向接口{}的真实类型的指针。
最近,我遇到了interface{}
的问题。我有一个类型为A的变量已通过interface{}
传递,方法Tt
定义为* A作为接收方。
我想调用方法Tt
但是失败了,因为变量在interface{}
中,我无法获得指向变量的指针。
如您所见,reflect.TypeOf(v)
提供了正确的类型A
,但reflect.TypeOf(&v)
提供了*interface {}
而不是*A
。
有没有办法获得*A
?
package main
import (
"fmt"
"reflect"
)
type SomeStruct1 struct{
}
type SomeStruct2 struct{
}
type SomeStruct3 struct{
}
etc...
func (*SomeStruct1) SomeMethod(){
fmt.Println("hello")
}
func (*SomeStruct2) SomeMethod(){
fmt.Println("hello")
}
func (*SomeStruct3) SomeMethod(){
fmt.Println("hello")
}
etc...
func DoSomething(arg interface{}){
switch v:=b.(type){
[]byte:{
dosomething for []byte
}
default:{
var m reflect.Value
if value.Kind() != reflect.Ptr {
m = reflect.ValueOf(&v).MethodByName("SomeMethod")
} else {
m = reflect.ValueOf(v).MethodByName("SomeMethod")
}
m.Call(nil)
}
}
func main() {
DoSomething([]byte{...})
DoSomething(SomeStruct1{})
DoSomething(&SomeStruct1{})
etc..
}
答案 0 :(得分:3)
使用反射:
//
// Return a pointer to the supplied struct via interface{}
//
func to_struct_ptr(obj interface{}) interface{} {
vp := reflect.New(reflect.TypeOf(obj))
vp.Elem().Set(reflect.ValueOf(obj))
return vp.Interface()
}
通过interface
传递T
,然后通过interface
获得*T
答案 1 :(得分:1)
要调用指针方法*A
,您必须拥有A
(或获取addressable A
值的地址。变量b
中的A
值不是addressable,因此无法通过b
访问a
指针方法。
修复方法是从var a A
var b interface{}
b = &a // Note change on this line
switch v := b.(type) {
default:
reflect.ValueOf(v).MethodByName("Tt").Call(nil)
}
:
reflect.ValueOf(v)
在调用v
中,ValueOf
中的值作为参数传递。 A
函数解包空接口以恢复类型reflect.ValueOf(&v)
的值。
在调用*interface{}
中,ValueOf
存储在空接口中,然后作为参数传递。 *interface{}
函数解包空接口以恢复类型v
的值。这是变量a
的地址,而不是变量var a A
var b interface{}
b = &a
switch v := b.(type) {
case interface {
Tt()
}:
v.Tt()
default:
fmt.Println("not handled")
}
的地址。
此特定示例中不需要反射:
// establish a connection
$db = Database::getInstance();
$mysqli = $db->getConnection();
// run sql
$sql = "SELECT * FROM `solutions` WHERE 1 LIMIT 6";
// run query
$result = $mysqli->query($sql);
// echo '<pre>'.var_export($result, TRUE).'</pre>';
// check query
if($result){
// echo '<pre>'.var_export($row, TRUE).'</pre>';
while($row = $result->fetch_assoc()){
echo '
<span class="solution">
// this section floats right
<div style="background-image:url('.$row['img_thumbnails'].'); " class="solution-img"></div><a href="solutions.php?key='.$row['solution_key'].'"><h2>'.$row['name'].'</h2></a>
<p>'.$row['headline_title_hook'].'</p>
</span>';
}
}else{
trigger_error('SQL has an error');
}
答案 2 :(得分:0)
你只需要输入。 例如:
type SomeStruct1 struct{
someList []string
}
func (s *SomeStruct1) print() {
fmt.Printf("%v\n", s.someList)
...
func Call(T interface{}){
switch T.(type){
case *SomeStruct1:
t := T.(*SomeStruct1) // cast as pointer to struct
t.print()
...
}
}
func main() {
a := SomeStruct{
someList: []string{"a", "b"}
}
Call(&a) // pass a as ptr
}