英文:
Accessing specific field of a generic struct passed to a variadic function
问题
假设我有一个名为foo
的通用结构体:
type foo[T any] struct {
data T
}
我有一个可变参数函数,我想要将一些foo
传递给它。它们可以是任何类型的foo
。我的理解是,因为foo[int]
和foo[string]
是不同的,所以我需要将省略号定义为any
类型,如下所示:
func bar(things ...any) {
for _, v := range things {
fmt.Println(v)
}
}
这确实可以工作。
func main() {
a := foo[string]{"cheese"}
b := foo[int]{42}
bar(a, b)
}
我的问题是,我想要特别访问每个foo
中的data
字段。但是如果我像这样定义bar
函数:
func bar(things ...any) {
for _, v := range things {
fmt.Println(v.data)
}
}
编译器会不可避免地感到不满,因为things
可以是任何类型,因此不能保证它们具有data
字段。
我知道将始终传递foo
,因此我知道将有一个名为data
的字段,但是我无法指定我只会传递foo
,像这样:
func bar(things ...foo) {
for _, v := range things {
fmt.Println(v.data)
}
}
因为foo
的类型没有指定。
如何将未指定数量的foo
传递给bar
函数,然后访问data
字段呢?
英文:
Say I have a generic struct
called foo
:
type foo[T any] struct {
data T
}
I have a variadic function that I want to pass some foo
s to. They could be any type of foo
. My understanding is that because a foo[int]
is different to a foo[string]
, I need to define my ellipsis as type any
, like so:
func bar(things ...any) {
for _, v := range things {
fmt.Println(v)
}
}
And this indeed works.
func main() {
a := foo[string]{"cheese"}
b := foo[int]{42}
bar(a, b)
}
My problem is that I want to specifically access the data
field in each foo
. But if I define bar
like this,
func bar(things ...any) {
for _, v := range things {
fmt.Println(v.data)
}
}
the compiler gets understandably upset, since things
could be anything and, therefore, there is no guarantee they have the field data
.
I know there will be a field called data
since I'm always passing foo
s, but I can't specify that I'll only pass foo
s, like this,
func bar(things ...foo) {
for _, v := range things {
fmt.Println(v.data)
}
}
because the type of foo
isn't specified.
How can I pass an unspecified number of foo
s to bar
and then access the data
field?
答案1
得分: 1
一种解决方案似乎是使用反射并使用FieldByName
访问字段:
func bar(things ...any) {
for _, v := range things {
x := reflect.ValueOf(v)
fmt.Println(x.FieldByName("data"))
}
}
不过,我不确定这是否会被认为是一个笨拙的解决方案,或者出于某种原因而具有危险性。可能需要在其中进行一些检查,以确保things
中的每个元素实际上都是某种类型的foo
,否则可能会尝试访问不存在的字段。
英文:
One solution seems to be to use reflection and to access the field using FieldByName
:
func bar(things ...any) {
for _, v := range things {
x := reflect.ValueOf(v)
fmt.Println(x.FieldByName("data"))
}
}
It's not clear to me though if this would be considered a cludge and/or dangerous for some reason or other. Presumably, I'd need some checking in there to ensure that everything in things
is actually a foo
of some variety or I could be trying to access a field that doesn't exist.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论