任何/接口{}作为约束与参数类型之间的区别?
由于仿制药已经在Go 1.18中发布了,因此我已经开始学习它们。我通常会得到这个概念,因为我过去有一些Java经验。但是我没有得到一些实施细节。
例如:当更合适地使用任何
而不是接口{}
时?这是一个示例:
func printInterface(foo interface{}) {
fmt.Printf("%v\n", foo)
}
func printAny[T any](foo T) {
fmt.Printf("%v\n", foo)
}
func (suite *TestSuite) TestString() {
printInterface("foo")
printAny("foo")
}
两个实现都起作用。但是,如果我尝试用任何 version打印
nil
,我将获得一个编译时错误:
不能推断t。
https://go.dev/play/pplay/p/0gmu4rhhaop
我赢了如果我尝试使用nil
使用接口{}
-version打印nil
,请获取此错误。
那么任何
的用例是什么?与简单地使用接口{}
相比,它带来了何时以及哪些好处?
我要求提供一个特定的示例,其中一种实现比另一个实现更合适和/或可以评估的特定受益。
As generics have been released in Go 1.18 pretty recently, I've started learning them. I generally get the concept, because I have some Java experience from the past. But I don't get some implementation specifics.
For instance: when it's more suitable to use any
instead of interface{}
? Here's an example:
func printInterface(foo interface{}) {
fmt.Printf("%v\n", foo)
}
func printAny[T any](foo T) {
fmt.Printf("%v\n", foo)
}
func (suite *TestSuite) TestString() {
printInterface("foo")
printAny("foo")
}
Both implementations work. However, if I try to print nil
with any
-version, I'll get a compile-time error:
cannot infer T.
https://go.dev/play/p/0gmU4rhhaOP
And I won't get this error if I try to print nil
with interface{}
-version.
So what's the use-case for any
? When and which benefits does it bring, compared to simply using interface{}
?
I'm asking to provide a specific example, where one implementation is objectively more suitable than another and/or where there is a specific benefit that can be evaluated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
任何
是别名 forinterface {}}
。 spec:接口类型:由于它是一个别名,因此您使用哪一个都没关系。他们是一个又一个。它们是可以互换的。您可以用另一个替换一个,代码将表示相同。
任何
较短,更清晰,但仅从GO 1.18起。由于它们是可互换的,因此这也有效:
printany()
不起作用的原因是它是具有类型参数的通用函数。要使用它,它必须为实例化(必须用已知类型分配其类型参数)。试图用nil
调用它不会带来任何类型信息,因此不能发生实例化,类型推断将无法使用。如果您使用
nil
值值,则可以使用类型信息,或者明确指定type param(在 go playground ):正如所说,
任何
都可以与interface> interface {}
互换,因此您'如果交换这两次出现,则LL具有相同的代码(在any
is an alias forinterface{}
. Spec: Interface types:Since it is an alias, it doesn't matter which one you use. They are one and the same. They are interchangeable. You can replace one with the other, the code will mean the same.
any
is shorter and clearer, but only works from Go 1.18.Since they are interchangeable, this also works:
The reason why
printAny()
doesn't work is due to it being a generic function with a type parameter. To use it, it must be instantiated (its type parameter must be assigned with a known type). Trying to call it withnil
carries no type information, so instantiation cannot happen, type inference won't work.If you call it with a
nil
value that carries type info, it'll work, or if you specify the type param explicitly (try it on the Go Playground):And as said,
any
is interchangeable withinterface{}
, so you'll have the same code if you swap both occurrences (try this one on the Go Playground):您的问题与
的使用无关。如您所见,从这个游乐场,如果您使用explicit类型实例化函数,则代码> PRINTANY [ANY](NIL)
它将起作用。如果您具有具有通用类型的功能,则需要指定类型。但是,GO编译器非常聪明,可以为您推断某些类型。但是
nil
仅是无法推断的。Your issue is not related to the usage of
any
/interface{}
— whose difference is purely cosmetic — but it is type inference. As you can see from this playground, if you instantiate your function with an explicit type, likeprintAny[any](nil)
it will work.If you have a function with generic type you need to specify the types. However the go compiler is very smart and can infer some types for you. But
nil
alone is impossible to infer.除了其他任何和
接口{}
是类型别名 - 因此,在用法中等效 -任何
作为类型都有实际差异参数和如您的示例中的任何
作为常规函数参数。区别在于,在
printany [t any](foo t)
foo
的类型不是任何
/接口>接口{} < /code>,但它是
t
。t
实例化是一种具体类型,它可能是接口本身也可能不是接口。然后,您只能将参数传递给可以分配给该混凝土类型的实例化printany
。通过多个参数,这如何影响您的代码最为明显。如果我们稍微更改函数签名:
实例化后:
printany
接受相同类型的任何两个参数 - 以实例化t
printInterface
,等效于printinterface(foo,bar Interface {})
仍然可以接受两个不同类型的参数,因为两者都会是 个体可分配到任何
/接口{}
。一个游乐场: https://go.dev/play/pplay/pdjp986cj96
注释:不能使用
nil
在没有显式类型参数的情况下使用,仅仅是因为nil
单独携带类型信息,因此编译器无法推断t
。但是,nil
通常可以分配给接口类型的变量。Beside
any
andinterface{}
being type aliases — hence, equivalent in usage —, there is a practical difference betweenany
as type parameter andany
as regular function argument, as in your example.The difference is that in
printAny[T any](foo T)
the type offoo
is notany
/interface{}
, but it'sT
. AndT
after instantiation is a concrete type, that may or may not be an interface itself. You can then only pass arguments to an instantiatedprintAny
that can be assigned to that concrete type.How this impacts your code is most evident with multiple arguments. If we change the function signatures a bit:
After instantiation:
printAny
accepts any two arguments of the same type — whichever is used to instantiateT
printInterface
, which is equivalent toprintInterface(foo, bar interface{})
can still accept two arguments of different types, since both would be individually assignable toany
/interface{}
.A playground: https://go.dev/play/p/pDjP986cj96
Note: the generic version cannot be called with
nil
without explicit type arguments simply becausenil
alone doesn't carry type information, so the compiler can't inferT
. Howevernil
can be normally assigned to variables of interface type.