泛型:处理具有相同数据成员类型的不同结构类型

huangapple go评论114阅读模式
英文:

go generics: processing different struct types with same data member types

问题

有两种结构类型,FooBar,都有一个int类型的数据成员val。我正在尝试编写一个通用函数,可以处理这两种类型。我尝试了以下代码,但不起作用。

  1. package main
  2. import "fmt"
  3. type Foo struct {
  4. val int
  5. }
  6. type Bar struct {
  7. val int
  8. }
  9. func Add[T any](slice []T) int {
  10. var sum int
  11. for _, elem := range slice {
  12. sum += elem.val
  13. }
  14. return sum
  15. }
  16. func Test() {
  17. f1 := Foo{val: 2}
  18. f2 := Foo{val: 2}
  19. fslice := []Foo{f1, f2}
  20. fsum := Add(fslice)
  21. fmt.Printf("fsum = %d\n", fsum)
  22. b1 := Bar{val: 3}
  23. b2 := Bar{val: 3}
  24. bslice := []Bar{b1, b2}
  25. bsum := Add(bslice)
  26. fmt.Printf("bsum = %d\n", bsum)
  27. }
  28. func main() {
  29. Test()
  30. }

编译器报错如下。

  1. $ go run generics1.go
  2. # command-line-arguments
  3. ./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.

  1. package main
  2. import "fmt"
  3. type Foo struct {
  4. val int
  5. }
  6. type Bar struct {
  7. val int
  8. }
  9. func Add[T any](slice []T) int {
  10. var sum int
  11. for _, elem := range slice {
  12. sum += elem.val
  13. }
  14. return sum
  15. }
  16. func Test() {
  17. f1 := Foo{val: 2}
  18. f2 := Foo{val: 2}
  19. fslice := []Foo{f1, f2}
  20. fsum := Add(fslice)
  21. fmt.Printf("fsum = %d\n", fsum)
  22. b1 := Bar{val: 3}
  23. b2 := Bar{val: 3}
  24. bslice := []Bar{b1, b2}
  25. bsum := Add(bslice)
  26. fmt.Printf("bsum = %d\n", bsum)
  27. }
  28. func main() {
  29. Test()
  30. }

The compiler throws the following error.

  1. $ go run generics1.go
  2. # command-line-arguments
  3. ./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

根据golang 1.18发布说明

Go编译器不支持访问类型参数类型的结构字段x.f,即使类型参数的类型集中的所有类型都有字段f。我们可能会在将来的版本中删除此限制。

你可以定义一个GetVal()接口方法来获取val,并将此方法作为泛型的类型约束的一部分。

示例代码:

  1. type Foo struct {
  2. val int
  3. }
  4. func (f Foo) GetVal() int {
  5. return f.val
  6. }
  7. type Bar struct {
  8. val int
  9. }
  10. func (b Bar) GetVal() int {
  11. return b.val
  12. }
  13. type MyType interface {
  14. Foo | Bar
  15. GetVal() int
  16. }
  17. func Add[T MyType](slice []T) int {
  18. var sum int
  19. for _, elem := range slice {
  20. sum += elem.GetVal()
  21. }
  22. return sum
  23. }

https://go.dev/play/p/0eJZpqy7q8f

英文:

Per golang 1.18 release note

> 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

  1. type Foo struct {
  2. val int
  3. }
  4. func (f Foo) GetVal() int {
  5. return f.val
  6. }
  7. type Bar struct {
  8. val int
  9. }
  10. func (b Bar) GetVal() int {
  11. return b.val
  12. }
  13. type MyType interface {
  14. Foo | Bar
  15. GetVal() int
  16. }
  17. func Add[T MyType](slice []T) int {
  18. var sum int
  19. for _, elem := range slice {
  20. sum += elem.GetVal()
  21. }
  22. return sum
  23. }

https://go.dev/play/p/0eJZpqy7q8f

huangapple
  • 本文由 发表于 2022年11月8日 09:19:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/74354709.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定