Home > Back-end >  Is there a way in Golang Generics to create something like "extends" in Typescript?
Is there a way in Golang Generics to create something like "extends" in Typescript?

Time:03-29

I am trying to create a function using Go Generics that accepts any structs that meet minimum struct criteria. Something like <T extends {name: string, age: number}> in Typescript.

Here below is my function and I am trying to find a way to make it work. I would love to be able to pass any struct that has Name string and Age int to the printNameAndAge function because that function will be using only these two fields. Is this possible? I was not able to find an example or documentation for this use case?

package main

import "fmt"

type User struct {
    Name   string
    Age    int
    Height float32
}

type Car struct {
    Age   int
    Name  string
    Model string
}

type NameAndAge struct {
    Name string
    Age  int
}


func printNameAndAge[T (**missing extends or something like that**) NameAndAge](u T) {
    fmt.Println(u.Name)
    fmt.Println(u.Age)
}

func main() {
    newUser := User{
        Name:   "John",
        Age:    24,
        Height: 186,
    }
    newCar := Car{
        Name:  "Series 3",
        Age:   1,
        Model: "BMW",
    }

    printNameAndAge(newUser)
    printNameAndAge(newCar)

}

CodePudding user response:

Use interfaces. Define interface with methods for common functionality. Implement those methods on each type.

package main

import "fmt"

type User struct {
    Name   string
    Age    int
    Height float32
}

func (u User) getName() string { return u.Name }
func (u User) getAge() int     { return u.Age }

type Car struct {
    Age   int
    Name  string
    Model string
}

func (c Car) getName() string { return c.Name }
func (c Car) getAge() int     { return c.Age }

func printNameAndAge(x interface {
    getName() string
    getAge() int
}) {
    fmt.Println(x.getName())
    fmt.Println(x.getAge())
}

func main() {
    newUser := User{
        Name:   "John",
        Age:    24,
        Height: 186,
    }
    newCar := Car{
        Name:  "Series 3",
        Age:   1,
        Model: "BMW",
    }

    printNameAndAge(newUser)
    printNameAndAge(newCar)

}

CodePudding user response:

You can try embed the substructure in your types like in the example below.

However the current solution is: interfaces

But hey thd type NameAndAge can have a method. And Car can expose this method via delegation.

type NameAndAge struct {
    Name string
    Age  int
}

func (na NameAndAge) Get()(string, int){
    return na.Name, na.Age
}

type Getter interface {
    Get()(string, int)
}

type Car struct {
    NameAndAge
    Model string
}

func Show(na NameAndAge) {
    fmt.Println(na.Name, na.Age)
}

func ShowInterface(g Getter){
    fmt.Println(g.Get())
}

func main() {
    var c Car
    c.Name = "Ford"
    c.Age = 40
    c.Model = "T"
    
    Show(c.NameAndAge)
    
    ShowInterface(c)

}
  •  Tags:  
  • go
  • Related