英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论