实例化具有任意类型的通用接口,结构体不实现它。

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

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]{ ... }

huangapple
  • 本文由 发表于 2023年2月14日 19:09:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75446958.html
匿名

发表评论

匿名网友

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

确定