Home >Backend Development >Golang >How to Make Go Functions Generic Using Interfaces: A Type Constraint Solution

How to Make Go Functions Generic Using Interfaces: A Type Constraint Solution

DDD
DDDOriginal
2024-10-27 02:28:30420browse

 How to Make Go Functions Generic Using Interfaces: A  Type Constraint Solution

Generic Method Parameters in Go: Solving the Issue of Type Constraints

Problem:

Consider the following Go code:

<code class="go">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 {
    IDs := make([]string, len(ms))
    for i, m := range ms {
        IDs[i] = strconv.Itoa(int(m.ID))
    }
    return &IDs
}

func main() {
    ... // Code to create Mammal and Human slices
    numberOfMammalIDs := Count(mammals)
    numberOfHumanIDs := Count(humans)
    fmt.Println(numberOfMammalIDs)
    fmt.Println(numberOfHumanIDs)
}</code>

This code fails to compile with the error error prog.go:39: cannot use humans (type []Human) as type []Mammal in argument to Count. The issue arises because the Count function expects an array of Mammal structs, but we are passing an array of Human structs. How can we resolve this type constraint and make the Count function generic enough to accept any type that has an ID property?

Solution:

1. Use Interfaces:

Replace the concrete types with interfaces that define the ID property. For example:

<code class="go">type Mammal interface {
    GetID() int
}

type Human interface {
    Mammal
    GetHairColor() string
}</code>

2. Embed Interfaces:

To avoid duplicating the ID method in both the Mammal and Human interfaces, use embedded interfaces:

<code class="go">type MammalImpl struct {
    ID int
    Name string
}

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

type HumanImpl struct {
    MammalImpl
    HairColor string
}</code>

3. Update Count Function:

Modify the Count function to use the Mammal interface instead of the concrete Mammal type:

<code class="go">func Count(ms []Mammal) *[]string {
    IDs := make([]string, len(ms))
    for i, m := range ms {
        IDs[i] = strconv.Itoa(m.GetID())
    }
    return &IDs
}</code>

4. Create Interface-Compliant Slices:

Create slices that implement the Mammal interface:

<code class="go">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"},
}</code>

5. Example Usage:

Example usage that now compiles successfully:

<code class="go">package main

import (
    "fmt"
    "strconv"
)

type Mammal interface {
    GetID() int
}

type Human interface {
    Mammal
    GetHairColor() string
}

type MammalImpl struct {
    ID   int
    Name string
}

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

type HumanImpl struct {
    MammalImpl
    HairColor string
}

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

func Count(ms []Mammal) *[]string {
    IDs := make([]string, len(ms))
    for i, m := range ms {
        IDs[i] = strconv.Itoa(m.GetID())
    }
    return &IDs
}

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

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

    numberOfMammalIDs := Count(mammals)
    numberOfHumanIDs := Count(humans)
    fmt.Println(numberOfMammalIDs) // [1 2]
    fmt.Println(numberOfHumanIDs) // [1 2]
}</code>

By using interfaces and embedded interfaces, we have made the Count function generic enough to handle any type that implements the Mammal interface, effectively solving the type constraint issue.

The above is the detailed content of How to Make Go Functions Generic Using Interfaces: A Type Constraint Solution. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn