Golang中的通用方法参数

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

Generic Method Parameters in Golang

问题

我需要帮助使其适用于任何类型。

我有一个函数,我需要接受具有ID属性的其他类型。

我尝试使用接口,但对于我的ID属性情况无效。以下是代码:

package main

import (
	"fmt"
	"strconv"
)

type Mammal struct {
	ID   int
	Name string
}

type Human struct {
	ID        int
	Name      string
	HairColor string
}

func Count(ms []Mammal) *[]string { // 如何使该函数接受任何类型而不仅仅是[]Mammal
	IDs := make([]string, len(ms))
	for i, m := range ms {
		IDs[i] = strconv.Itoa(int(m.ID))
	}
	return &IDs
}

func main() {
	mammals := []Mammal{
		Mammal{1, "Carnivorious"},
		Mammal{2, "Ominivorious"},
	}

	humans := []Human{
		Human{ID: 1, Name: "Peter", HairColor: "Black"},
		Human{ID: 2, Name: "Paul", HairColor: "Red"},
	}
	numberOfMammalIDs := Count(mammals)
	numberOfHumanIDs := Count(humans)
	fmt.Println(numberOfMammalIDs)
	fmt.Println(numberOfHumanIDs)
}

我得到以下错误:

error prog.go:39: cannot use humans (type []Human) as type []Mammal in argument to Count

请在此处查看更多详细信息:Go Playground

英文:

I need help with making this work for any type.

I have got a function I need to accept other types that have ID property.

I have tried using interfaces but that did not work for my ID property case. Here is the code:

package main


import (
  "fmt"
  "strconv"
  )

type Mammal struct{
  ID int
  Name string 
}

type Human struct {  
  ID int
  Name string 
  HairColor string
}

func Count(ms []Mammal) *[]string { // How can i get this function to accept any type not just []Mammal
   IDs := make([]string, len(ms))
   for i, m := range ms {
     IDs[i] = strconv.Itoa(int(m.ID))
   }
   return &IDs
}

func main(){
  mammals := []Mammal{
    Mammal{1, "Carnivorious"},
    Mammal{2, "Ominivorious"},
  }
  
  humans := []Human{
    Human{ID:1, Name: "Peter", HairColor: "Black"},
    Human{ID:2, Name: "Paul", HairColor: "Red"},
  } 
  numberOfMammalIDs := Count(mammals)
  numberOfHumanIDs := Count(humans)
  fmt.Println(numberOfMammalIDs)
  fmt.Println(numberOfHumanIDs)
}

I get this

> error prog.go:39: cannot use humans (type []Human) as type []Mammal in argument to Count

See Go Playground for more details here http://play.golang.org/p/xzWgjkzcmH

答案1

得分: 6

使用接口而不是具体类型,并使用嵌入接口,这样通用方法就不必在两个类型中都列出:

type Mammal interface {
    GetID() int
    GetName() string
}

type Human interface {
    Mammal

    GetHairColor() string
}

以下是基于您使用嵌入类型(结构体)的代码的接口实现:

type MammalImpl struct {
    ID   int
    Name string
}

func (m MammalImpl) GetID() int {
    return m.ID
}

func (m MammalImpl) GetName() string {
    return m.Name
}

type HumanImpl struct {
    MammalImpl
    HairColor string
}

func (h HumanImpl) GetHairColor() string {
    return h.HairColor
}

但是在您的 Count() 函数中,您只能引用方法而不是实现的字段:

IDs[i] = strconv.Itoa(m.GetID())  // 通过方法访问 ID:GetID()

创建 Mammals 和 Humans 的切片:

mammals := []Mammal{
    MammalImpl{1, "Carnivorious"},
    MammalImpl{2, "Ominivorious"},
}

humans := []Mammal{
    HumanImpl{MammalImpl: MammalImpl{ID: 1, Name: "Peter"}, HairColor: "Black"},
    HumanImpl{MammalImpl: MammalImpl{ID: 2, Name: "Paul"}, HairColor: "Red"},
}

完整的可工作代码请参见 Go Playground

英文:

Use interfaces instead of concrete types, and use embedded interfaces so the common methods do not have to be listed in both types:

type Mammal interface {
	GetID() int
	GetName() string
}

type Human interface {
	Mammal

	GetHairColor() string
}

And here is the implementation of these interfaces based on your code which uses embedded types (structs):

type MammalImpl struct {
	ID   int
	Name string
}

func (m MammalImpl) GetID() int {
	return m.ID
}

func (m MammalImpl) GetName() string {
	return m.Name
}

type HumanImpl struct {
	MammalImpl
	HairColor string
}

func (h HumanImpl) GetHairColor() string {
	return h.HairColor
}

But then of course in your Count() function you can only refer to the method and not the field of the implementation:

IDs[i] = strconv.Itoa(m.GetID())  // Access ID via the method: GetID()

And creating your slices of Mammals and Humans:

mammals := []Mammal{
	MammalImpl{1, "Carnivorious"},
	MammalImpl{2, "Ominivorious"},
}

humans := []Mammal{
	HumanImpl{MammalImpl: MammalImpl{ID: 1, Name: "Peter"}, HairColor: "Black"},
	HumanImpl{MammalImpl: MammalImpl{ID: 2, Name: "Paul"}, HairColor: "Red"},
}

Here is the complete working code on Go Playground.

答案2

得分: 6

你在Go语言中无法完全按照你的要求做到。在Go语言中,最接近你要求的方法可能是下面代码中所示的方式:

type Ids interface {
  Id() int
}

func (this Mammal) Id() int {
  return this.ID
} 

func (this Human) Id() int {
  return this.ID
} 


func Count(ms []Ids) *[]string {
...
    IDs[i] = strconv.Itoa(int(m.Id()))
...
}

func main() {
  mammals := []Ids{
    Mammal{1, "Carnivorious"},
    Mammal{2, "Ominivorious"},
  }

  humans := []Ids{
    Human{ID:1, Name: "Peter", HairColor: "Black"},
    Human{ID:2, Name: "Paul", HairColor: "Red"},
  }
  ...
}

这里是一个可工作的示例

英文:

You can't do precisely what you ask for in Go. Closest way to do things in Go would be something like this as shown in code below:

type Ids interface{
  Id() int
}

func (this Mammal) Id() int{
  return this.ID
} 

func (this Human) Id() int{
  return this.ID
} 


func Count(ms []Ids) *[]string {
...
    IDs[i] = strconv.Itoa(int(m.Id()))
...
}

func main(){
  mammals := []Ids{
    Mammal{1, "Carnivorious"},
    Mammal{2, "Ominivorious"},
  }

  humans := []Ids{
    Human{ID:1, Name: "Peter", HairColor: "Black"},
    Human{ID:2, Name: "Paul", HairColor: "Red"},
  }
  ...
}  

here is the working example

huangapple
  • 本文由 发表于 2015年2月8日 18:59:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/28393166.html
匿名

发表评论

匿名网友

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

确定