有了Go语言1.18中的新泛型,我认为可以创建一个'Either[A,B]'类型,用来表示某个对象可以是类型A或者类型B。
在函数可能返回两个可能值之一作为结果(例如,一个用于“正常”结果,一个用于错误)的情况下,可能会使用此选项。
我知道Go语言的“惯用"错误是同时返回一个”正常“值和一个错误值,返回一个nil值。但是......让我有点困扰的是,我们实际上是在说”this returns AandB“,而我们真正想说的是”this returns AorB“。
所以我想也许我们可以在这里做得更好,我想这也是一个很好的练习,看看/测试我们可以用这些新的泛型做什么。
遗憾的是,尽管我已经尝试过了,但到目前为止我还不能完成这个练习,也不能让任何东西工作/编译。从我的一次失败尝试中,我想 * 以某种方式 * 实现一个接口:
//A value of type `Either[A,B]` holds one value which can be either of type A or type B.
type Either[A any, B any] interface {
// Call either one of two functions depending on whether the value is an A or B
// and return the result.
Switch[R any]( // <=== ERROR: interface methods must have no type parameters
onA func(a A) R),
onB func(b B) R),
) R
}
不幸的是,这很快就失败了,因为Go语言不允许声明这个接口,显然是因为“接口方法不能有类型参数”。
我们该如何解决这个限制呢?或者说,在Go语言中没有办法创建一个“类型”来准确地表达“这个东西是/返回A或B”的想法(而不是A和B的元组)。
4条答案
按热度按时间5tmbdcev1#
Either
可以被建模为一个结构类型,其中有一个any
/interface{}
类型的未导出字段。类型参数可以用来确保某种程度的编译时类型安全:如果
Switch
必须声明为方法,它不能在R
中单独参数化。额外的类型参数必须在类型定义中声明,但这可能会使用法有点麻烦,因为在示例化时必须选择R
。独立函数似乎更好-在同一个包中,访问未导出的字段:
一个操场的一些代码和用法:https://go.dev/play/p/g-NmE4KZVq2
jogvjijk2#
如果我必须这样做,我会查找一个函数式编程语言(如OCaml),并敲掉他们的解决方案的任何一种类型。
ioekq8ef3#
我终于想到了一个解决方案。关键是将“Either”类型定义为“struct”而不是接口。
这是可行的,但"代价“是我们实际上仍然使用”类似元组“的实现,即我们存储A和B,但确保只能通过公共API使用其中一个。
我想这是我们能做的最好的了......鉴于吴王对我们的限制。
如果有人有一个“变通办法”,基本上不使用“元组”来表示“联合”。我会认为这是一个更好的答案。
dxxyhpgq4#
您可以使用https://github.com/samber/mo库(免责声明:我是项目作者)。
任一签名为:
以下是一些例子:
您关于
Switch
模式的问题可以通过以下方式实现: