尝试在 Go 中重新创建 Java Options(出于学习目的)。有趣的是,直接返回值与通过变量赋值返回值有不同的行为,一个可以工作,另一个则不能。 在 Of 方法中,当我返回
EmptyOptional
时,我收到编译时错误,但是当我返回 &optional[TT]{}
时,它的工作正常。
package utils
type TT interface{}
type Optional[T TT] interface {
Of(t T) Optional[T]
Map(func() Optional[T]) Optional[T]
}
var EmptyOptional = &optional[TT]{}
type optional[T any] struct {
t T
}
func (o *optional[TT]) Of(t TT) Optional[TT] {
if t == nil {
// return &optional[TT]{} // <<-- Working
return EmptyOptional // <<-- Not Working
}
return nil
}
func (o *optional[TT]) Map(func() Optional[TT]) Optional[TT] {
return nil
}
编译时错误
./prog.go:24:10: cannot use EmptyOptional (variable of type *optional[TT]) as Optional[TT] value in return statement: *optional[TT] does not implement Optional[TT] (wrong type for method Map)
have Map(func() main.Optional[main.TT]) main.Optional[main.TT]
want Map(func() main.Optional[TT]) main.Optional[TT]
今天是第一周。我尽力理解这种行为叫什么。
你遇到的问题比你承认的还要多。将您的代码放在游乐场中,编译器无法访问您声称“有效”的代码,因为它包含在具有无效谓词的
if
子句中:
invalid operation: t == nil (mismatched types TT and untyped nil)
在 Go Playground 中创建 MVCE 可以帮助消除此类问题,并呈现一个人们可以参与并致力于帮助解决您的问题的场景(这样做可能会帮助您自己认识到问题)。
抛开这个问题,并忽略这样一个事实:尝试在 Go 中重新创建 Java 选项对于学习练习来说没有什么价值......问题
EmptyOptional
是实例化
optional[T]
类型的值,其中
T
属于
TT
类型(与现有
any
类型完全相同的类型的冗余重新声明)。
Of
方法是泛型类型
Optional[T]
的方法。
Of
可以返回
EmptyOptional
的唯一场景是
Optional[T]
的类型参数与
EmptyOptional
的实例类型相同的特定情况:即
TT
.但是由于
Of
方法必须返回泛型类型的值,因此尝试返回某些具体类型的特定值是不可能的。简化以澄清
package utils
type Optional[T any] interface {
Of(t T) Optional[T]
}
var EmptyOptional = &optional[any]{}
type optional[T any] struct {
t T
}
func (o *optional[T]) Of(t T) Optional[T] {
//return &optional[T]{} // <<-- Working
return EmptyOptional // <<-- Not Working: a value of concrete type is never compatible with a generic
}
如果您愿意,这也可以在游乐场中进行进一步探索。 声明。我还删除了多余的 TT
接口和不必要的
Map
方法,因为这些与问题完全无关。从这个简化的例子中可以明显看出,
EmptyOptional
具有特定类型参数的泛型类型的具体实例化
(
any
)不能在Optional[T]
(即尚未实例化)的地方使用)通用。
考虑这个假设:
type OptionalInt optional[int]
这会使用返回
Of[int]
的 Optional[int]
方法实例化一个类型,但
EmptyOptional
的类型为
Optional[any]
。
补充即使使用相同的类型参数实例化,实例化的泛型类型也不兼容;它们始终是不同的类型,如
在 GoLang 中实现可选性(行为,而不是类型)的惯用方法是简单地使用指针,并用
nil
not present
属性。泛型不涉及此。
习惯了这个,你会发现它更简单。