在Golang泛型中是否有一种类似于Typescript中的”extends”的方式?

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

Is there a way in Golang Generics to create something like "extends" in Typescript?

问题

我正在尝试使用Go泛型创建一个函数,该函数接受满足最小结构条件的任何结构体。类似于TypeScript中的<T extends {name: string, age: number}>

以下是我的函数,我正在尝试找到一种使其工作的方法。我希望能够将任何具有Name stringAge int字段的结构体传递给printNameAndAge函数,因为该函数只使用这两个字段。这种情况是否可行?我找不到这种用例的示例或文档。

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 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)
}

请注意,Go语言目前还不支持泛型,因此上述代码只是一种示例,展示了您可能希望实现的功能。

英文:

I am trying to create a function using Go Generics that accepts any structs that meet minimum struct criteria. Something like &lt;T extends {name: string, age: number}&gt; 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 &quot;fmt&quot;

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:   &quot;John&quot;,
		Age:    24,
		Height: 186,
	}
	newCar := Car{
		Name:  &quot;Series 3&quot;,
		Age:   1,
		Model: &quot;BMW&quot;,
	}

	printNameAndAge(newUser)
	printNameAndAge(newCar)

}

答案1

得分: 1

使用接口。为常见功能定义具有方法的接口。在每个类型上实现这些方法。

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)

}

请注意,这是一个使用Go语言编写的示例代码,它使用接口来实现通用功能。在代码中定义了UserCar两个结构体,并为它们分别实现了getName()getAge()方法。然后,通过printNameAndAge()函数,可以打印出任何实现了getName()getAge()方法的类型的名称和年龄。在main()函数中,创建了一个User类型的实例newUser和一个Car类型的实例newCar,并分别传递给printNameAndAge()函数进行打印。

英文:

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

package main

import &quot;fmt&quot;

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:   &quot;John&quot;,
		Age:    24,
		Height: 186,
	}
	newCar := Car{
		Name:  &quot;Series 3&quot;,
		Age:   1,
		Model: &quot;BMW&quot;,
	}

	printNameAndAge(newUser)
	printNameAndAge(newCar)

}

答案2

得分: -1

你可以尝试像下面的示例中那样将子结构嵌入到你的类型中。

然而,当前的解决方案是:接口

但是,类型NameAndAge可以有一个方法。Car可以通过委托公开这个方法。

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)

}
英文:

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 = &quot;Ford&quot;
	c.Age = 40
	c.Model = &quot;T&quot;
    
	Show(c.NameAndAge)
    
    ShowInterface(c)

}


</details>



huangapple
  • 本文由 发表于 2022年3月29日 05:01:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/71653698.html
匿名

发表评论

匿名网友

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

确定