英文:
go generics: processing different struct types with same data member types
问题
有两种结构类型,Foo
和Bar
,都有一个int
类型的数据成员val
。我正在尝试编写一个通用函数,可以处理这两种类型。我尝试了以下代码,但不起作用。
package main
import "fmt"
type Foo struct {
val int
}
type Bar struct {
val int
}
func Add[T any](slice []T) int {
var sum int
for _, elem := range slice {
sum += elem.val
}
return sum
}
func Test() {
f1 := Foo{val: 2}
f2 := Foo{val: 2}
fslice := []Foo{f1, f2}
fsum := Add(fslice)
fmt.Printf("fsum = %d\n", fsum)
b1 := Bar{val: 3}
b2 := Bar{val: 3}
bslice := []Bar{b1, b2}
bsum := Add(bslice)
fmt.Printf("bsum = %d\n", bsum)
}
func main() {
Test()
}
编译器报错如下。
$ go run generics1.go
# command-line-arguments
./generics1.go:16:15: elem.val undefined (type T has no field or method val)
Go Playground链接:https://go.dev/play/p/mdOMH3xuwu7
有什么可能的方法来解决这个问题?
英文:
There are two struct types, Foo
and Bar
, with an int
data member val
. I am trying to write a generic function that can handle both types. I tried the following and this did not work.
package main
import "fmt"
type Foo struct {
val int
}
type Bar struct {
val int
}
func Add[T any](slice []T) int {
var sum int
for _, elem := range slice {
sum += elem.val
}
return sum
}
func Test() {
f1 := Foo{val: 2}
f2 := Foo{val: 2}
fslice := []Foo{f1, f2}
fsum := Add(fslice)
fmt.Printf("fsum = %d\n", fsum)
b1 := Bar{val: 3}
b2 := Bar{val: 3}
bslice := []Bar{b1, b2}
bsum := Add(bslice)
fmt.Printf("bsum = %d\n", bsum)
}
func main() {
Test()
}
The compiler throws the following error.
$ go run generics1.go
# command-line-arguments
./generics1.go:16:15: elem.val undefined (type T has no field or method val)
Go playground link: https://go.dev/play/p/mdOMH3xuwu7
What could be a possible way to approach this?
答案1
得分: 2
Go编译器不支持访问类型参数类型的结构字段x.f,即使类型参数的类型集中的所有类型都有字段f。我们可能会在将来的版本中删除此限制。
你可以定义一个GetVal()
接口方法来获取val
,并将此方法作为泛型的类型约束的一部分。
示例代码:
type Foo struct {
val int
}
func (f Foo) GetVal() int {
return f.val
}
type Bar struct {
val int
}
func (b Bar) GetVal() int {
return b.val
}
type MyType interface {
Foo | Bar
GetVal() int
}
func Add[T MyType](slice []T) int {
var sum int
for _, elem := range slice {
sum += elem.GetVal()
}
return sum
}
https://go.dev/play/p/0eJZpqy7q8f
英文:
> The Go compiler does not support accessing a struct field x.f where x is of type parameter type even if all types in the type parameter's type set have a field f. We may remove this restriction in a future release.
You could define one GetVal()
interface method to retrieve the val
, and use this method as part of type constraint of generic.
Sample codes
type Foo struct {
val int
}
func (f Foo) GetVal() int {
return f.val
}
type Bar struct {
val int
}
func (b Bar) GetVal() int {
return b.val
}
type MyType interface {
Foo | Bar
GetVal() int
}
func Add[T MyType](slice []T) int {
var sum int
for _, elem := range slice {
sum += elem.GetVal()
}
return sum
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论