英文:
Instantiate generic interface with any, struct doesn't implement it
问题
有人能解释一下为什么*DataTo不能满足ToType[any]吗?
我试图构建一个DTOer,它将一个结构体的所有值复制到另一个结构体,并设置一些显式的值(在这个例子中是V)。
以下是代码链接:https://go.dev/play/p/-oobZrw5Ewe
package main
import "fmt"
type DataFrom struct {
V1 int
}
type DataTo struct {
V int
}
func (m *DataTo) SetVal() {
m.V = 1
return
}
type ToType[T any] interface {
SetVal()
*T
}
type DTO[TFrom any, TTo ToType[any]] struct {
Get func(from TFrom) TTo
}
func main() {
dto := &DTO[DataFrom, *DataTo]{
Get: func(from DataFrom) *DataTo {
return &DataTo{V: from.V1 + 666}
},
}
vFrom := DataFrom{V1: 1}
vTo := dto.Get(vFrom)
fmt.Println(vTo.V)
}
英文:
Can someone explain, why *DataTo does not satisfy ToType[any]?
Trying to build a DTOer, that copies all values of one struct to another and also sets some explicit values (V in this case)
https://go.dev/play/p/-oobZrw5Ewe
// You can edit this code!
// Click here and start typing.
package main
import "fmt"
type DataFrom struct {
V1 int
}
type DataTo struct {
V int
}
func (m *DataTo) SetVal() {
m.V = 1
return
}
type ToType[T any] interface {
SetVal()
*T
}
type DTO[TFrom any, TTo ToType[any]] struct {
Get func(from TFrom) TTo
}
func main() {
dto := &DTO[DataFrom, *DataTo]{
Get: func(from DataFrom) *DataTo {
return &DataTo{V: from.V1 + 666}
},
}
vFrom := DataFrom{V1: 1}
vTo := dto.Get(vFrom)
fmt.Println(vTo.V)
}
答案1
得分: 2
因为any是一个静态类型。
如果你用它来实例化一个泛型类型,比如ToType,那个泛型类型将会期望精确的any。
现在,某些类型参数的用法可能会隐藏这个问题,例如:
type Foo[T any] struct {
Value T
}
Foo[any]{Value: 12} // ok
通常情况下,你可以像上面那样给any赋予任何类型,因为any只是空接口interface{}的别名,任何类型都满足空接口。
当类型参数在*T等复合类型中使用时,用any实例化意味着精确地是*any。因此,你可以将ToType[any]想象成与以下内容相同:
type ToTypeAny interface {
SetVal()
*any
}
然后*DataTo显然不是*any。更多细节请参考:https://stackoverflow.com/questions/68725213/assign-struct-pointer-to-interface-pointer
如果你将结构体声明如下,它将会编译通过:
type DTO[TFrom any, TTo ToType[DataTo]] struct {
Get func(from TFrom) TTo
}
或者以一种更"通用"但也更冗长的方式:
type DTO[TFrom any, T any, TTo ToType[T]] struct {
Get func(from TFrom) TTo
}
&DTO[DataFrom, DataTo, *DataTo]{ ... }
英文:
Because any is a static type.
If you use it to instantiate a generic type like ToType, that generic type will expect exactly any.
Now, certain usages of the type parameter might hide this issue, for example:
type Foo[T any] struct {
Value T
}
Foo[any]{Value: 12} // ok
Normally you are able to assign whatever type to any like the above, because any is just an alias of the empty interface interface{}, and any type satisfies the empty interface.
When the type parameter is used in composite types such as *T, then instantiating with any means exactly *any. Therefore you can imagine ToType[any] as the same thing as:
type ToTypeAny interface {
SetVal()
*any
}
And then *DataTo is obviously not *any. Further details: https://stackoverflow.com/questions/68725213/assign-struct-pointer-to-interface-pointer
If you declare the struct as follows it will compile:
type DTO[TFrom any, TTo ToType[DataTo]] struct {
Get func(from TFrom) TTo
}
Or in a more "generic" but also more verbose way:
type DTO[TFrom any, T any, TTo ToType[T]] struct {
Get func(from TFrom) TTo
}
&DTO[DataFrom, DataTo, *DataTo]{ ... }
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论