英文:
go (reflect): How to Instantiate an arbitrary type and set a known embedded field
问题
考虑以下类型声明:
type (
Embedded struct{}
Actual1 struct{ *Embedded }
Actual2 struct{ *Embedded }
Actual3 struct{ *Embedded }
)
现在考虑以下函数,其中 i
可能是类型 Actual1
、Actual2
或 Actual3
(或任何其他以类似方式嵌入 Embedded
的类型)。我无法进行类型断言或类型切换,因为我无法知道有多少类型包含 Embedded
,我只知道关于 i
的是它确实嵌入了 Embedded
类型。该函数将实例化一个与 i
相同类型的新实例,并在该新实例上设置 embed
。
func New(i interface{}, field *Embedded) interface{} {
// 步骤 1. 实例化与 `i` 具有相同底层类型的新实例
// 步骤 2. 将 `i.Embedded` 设置为 `field`
// 步骤 3. 返回新实例。
}
下面是用法示例:
func main() {
actual := &Actual1{}
embed := &Embedded{}
copied := New(actual, embed)
if copied.(Actual1).Embedded != embed {
log.Fatal("It didn't work!")
}
}
一个正确的 New(...)
函数的实现不能使用类型断言或类型切换,并且也不会导致上述调用 log.Fatal
。
我认为我正在请求的是这两个问题的结合:
英文:
Consider the following type declaration:
type (
Embedded struct{}
Actual1 struct{ *Embedded }
Actual2 struct{ *Embedded }
Actual3 struct{ *Embedded }
)
Now consider the following function, where i
may be of type Actual1
, Actual2
, or Actual3
(or any other type that embeds Embedded
in like manner). I can't do a type assertion or a type switch because I can't know how many types contain Embedded
, all I know about i
is that it does indeed embed the Embedded
type. This function will instantiate a new instance of the same type as i
and set embed
on that newly instantiated copy instance.
func New(i interface{}, field *Embedded) interface{} {
// Step 1. instantiate new instance of `i`, of same underlying type as `i`
// Step 2. set `i.Embedded` to `field`
// Step 3. return the new instance.
}
Here's what usage would look like:
func main() {
actual := &Actual1{}
embed := &Embedded{}
copied := New(actual, embed)
if copied.(Actual1).Embedded != embed {
log.Fatal("It didn't work!")
}
}
A correct implementation of the New(...)
function cannot use type assertions or a type switch and would also not result in the call to log.Fatal
shown above.
I think what I'm asking for is a combination of these two questions:
答案1
得分: 2
使用反射,你可以这样做:
- 从指向结构体的指针的类型中获取结构体的类型
- 实例化并解引用它
- 使用指定的字段名称查找字段,并将其值设置为指针的值
代码:
v := reflect.New(reflect.TypeOf(i).Elem()).Elem()
f := reflect.ValueOf(field)
v.FieldByName("Embedded").Set(f)
return v.Interface()
Playground: http://play.golang.org/p/fX413svXDv
英文:
Using reflection, you can do it like that:
- get the type of the struct from the type of the pointer to it
- instantiate and deref it
- set the value of the field (looking it up by name) with the value of your pointer
Code:
v := reflect.New(reflect.TypeOf(i).Elem()).Elem()
f := reflect.ValueOf(field)
v.FieldByName("Embedded").Set(f)
return v.Interface()
Playground: http://play.golang.org/p/fX413svXDv
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论