GoLang – Generics instead of interface to return different types

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

GoLang - Generics instead of interface to return different types

问题

我阅读了很多文档,但没有找到是否可以这样做的信息。

在Go中,是否有一种方法可以在不使用接口作为返回类型的情况下实现这样的功能?

以下是一个示例代码:

package main

import "fmt"

type Foo struct {
	Id       uint
	FooField string
}

type Bar struct {
	Id       uint
	BarField string
}

type Model interface {
	Foo | Bar
}

func build[T Model](s string) T {
	if s == "foo" {
		fmt.Println(s)
		return Foo{}
	}
	fmt.Println(s)
	return Bar{}
}

func main() {
	build("foo")
}

你可以在这里找到一个Playground示例。

英文:

I read a lot of docs but I couldn't find if I'm able to do it.

Is there a way to do something like this in Go without use an interface as return type?

Playground example

package main

import "fmt"

type Foo struct {
	Id uint
	FooField string
}

type Bar struct {
	Id uint
	BarField string
}

type Model interface {
	Foo | Bar
}

func build[T Model](s string) T {
	if s == "foo" {
		fmt.Println(s)
		return Foo{}
	}
	fmt.Println(s)
	return Bar{}
}

func main() {
	build("foo")
}

答案1

得分: 1

不,至少不是你在这里展示的方式。

Go是一种静态类型语言,这意味着值的语义数据类型不依赖于程序中的任何动态值。

接口并不是一个例外,而是一种扩展。根据语言规范(摘录):

变量的静态类型(或简称为类型)是在其声明中给出的类型。接口类型的变量还具有一个独特的动态类型,它是在运行时分配给变量的值的(非接口)类型。

这是一个可以工作的替代版本。

func build[T Model]() T {
    var x T
    return x
}

func main() {
    //    VVV 显式传递类型参数,而不是字符串
    build[Foo]()
}

之所以这个版本是有效的而你的版本不是,是因为现在返回类型仅取决于提供的类型参数,这始终是静态的。当编译器可以推断出类型参数时,类型参数通常被完全省略,但在这种情况下,明确列出它们是最正确的做法。

英文:

No, at least not how you've shown here.

Go is a statically typed language, meaning that the semantic data types of values do not depend on any dynamic values in the program.

Interfaces are not an exception to this, but an extension. From the language specification (abridged):
> The static type (or just type) of a variable is the type given in its declaration. Variables of interface type also have a distinct dynamic type, which is the (non-interface) type of the value assigned to the variable at run time.

Here's an alternate version that would work.

func build[T Model]() T {
    var x T
    return x
}

func main() {
    //    VVV explicitly passing the type parameter, not a string
    build[Foo]()
}

The reason why this is valid and yours isn't, is because now the return type only depends on the type parameter provided, which is always static. Type parameters are often omitted entirely when they can be inferred by the compiler, but in cases like this, it's most correct to list them explicitly.

huangapple
  • 本文由 发表于 2022年8月6日 10:02:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/73256691.html
匿名

发表评论

匿名网友

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

确定