近期我们在分享《3 件与 Go 开发者有关的大小事》时,里面有一部分有提到 Go 泛型的约束类型语法又又又变了。

在评论区里看到不少的读者朋友大呼泛型的新类型约束语法挺丑,不如原本的好...

如下:

图片

为此,今天煎鱼就带大家来看看,为什么会发生泛型的新语法会这种改变?

问题背景

原本 @Ian Lance Taylor 设计的的泛型类型关键字如下:

type T interface {type int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, float32, float64, complex64, complex128, string
}

看起来好像非常 “顺眼”。但在《proposal: Go 2: sum types using interface type lists[1]》中社区进行了热烈的讨论。

认为该类型约束的关键字,过于 “模棱两可”。像是 @Damien Neil 所提出的以下两个例子。

结构体的例子:

package p
type mustIncludeDefaultCase struct{}
type MySum interface {type int, float64, mustIncludeDefaultCase
}

不明确的点之一,如果类型列表包含一个未导出的类型,那又应该是如何处理呢?

接口的例子:

type T interface { type int16, int32 }
func main() {var x Tswitch x.(type) {case int16:case int32:}
}

你认为程序会跑进哪个 switch-case 的代码块里呢,是 int16,还是 int32?

不,都不会,变量 x 是 nil,如此迷惑。

在社区讨论中,发现设计与真实场景一结合,发现这个类型规则在普通的接口类型、在约束中使用也太微妙了。

用类型列表嵌入接口时的行为也很奇怪。认为可以做的更好,那就是 “更显式”。

新提案

为此,Go 泛型的设计者 @Ian Lance Taylor 提出了一个新的提案《spec: generics: use type sets to remove type keyword in constraints[2]》。

其包含三个新的、更简单的想法来取代泛型提案中定义的类型列表。

关键名词

新语法在泛型处增加一个新概念:接口元素(interface elements),用作约束条件的接口类型,或者被嵌入约束条件的接口类型,允许嵌入一些额外的构造。

被嵌入的可以是:

  • 任何类型,而不仅仅是一个接口类型。

  • 一个新的句法结构,称为近似元素。

  • 一个新的句法结构,称为联合元素。

重点名词,我们继续展开讲解,分别是:

  • 嵌入约束。

  • 近似元素。

  • 联合元素。

  • 接口类型。

联合元素

原先的语法中,类型约束会用逗号分隔的方式来展示。

如下:

type int, int8, int16, int32, int64

在新语法中,结合定义为 union element(联合元素),写成一系列由竖线 ”|“ 分隔的类型或近似元素。

如下:

type PredeclaredSignedInteger interface {int | int8 | int16 | int32 | int64
}

常常会和下面讲到的近似元素一起使用。

近似元素

新语法,他的标识符是 “~”,完整用法是 ~T~T 是指底层类型为 T 的所有类型的集合。例如:

type AnyInt interface{ ~int }

他的类型集是 ~int,也就是所有类型为 int 的类型(如:int、int8、int16、int32、int64)都能够满足这个类型约束的条件。

再结合以上的分隔来使用,用法为:

type SignedInteger interface {~int | ~int8 | ~int16 | ~int32 | ~int64
}

相当于泛型提案中使用的以下类型:

interface {type int, int8, int16, int32, int64
}

新语法只需借助近似标识符 ~int 来表达就可以了,更明确的表示了近似匹配,而不是存在隐式理解。

嵌入约束

一个类型约束可以嵌入另一个约束,联合元素可以包括约束。

例如:

// Signed is a constraint whose type set is any signed integer type.
type Signed interface {~int | ~int8 | ~int16 | ~int32 | ~int64
}// Unsigned is a constraint whose type set is any unsigned integer type.
type Unsigned interface {~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
}// Float is a constraint whose type set is any floating point type.
type Float interface {~float32 | ~float64
}// Ordered is a constraint whose type set is any ordered type.
// That is, any type that supports the < operator.
type Ordered interface {Signed | Unsigned | Float | ~string
}

这个很好理解,就是正式支持嵌入约束了。

接口类型(联合约束元素)

在联合元素中,使用接口类型的话。将会把该类型集添加到联合中。

例如:

type Stringish interface {string | fmt.Stringer
}

Stringish 的类型集将是字符串类型和所有实现 fmt.Stringer 的类型,任何这些类型(包括 fmt.Stringer 本身)将被允许作为这个约束的类型参数。

也就是针对接口类型做了特殊的处理。

总结

今天这篇文章,主要讲解了 Go 泛型的新语法,其实本质上还是为了解决引入 A 后,出现了 BCD 新问题,又继续引入新的语法和模式来解决。

整体就是三个观点:

  • 显式匹配:使用明确的 "~" 近似元素,澄清了何时在底层类型上进行匹配

  • 明确含义:使用 “|” 而不是 “,” 强调这是一个元素的联合

  • 嵌套优化:通过允许约束嵌入非界面元素,类型关键字可以被省略。

这就是用这两个新语法符号的原因,被嫌丑的新语法标识符 “|” 和 “~” ,其实也是在 issues 的大范围讨论中,由社区贡献出来的。

算是有利有弊?你的看法如何,欢迎在评论区留言:)

参考资料

[1]proposal: Go 2: sum types using interface type lists: https://github.com/golang/go/issues/41716

[2]spec: generics: use type sets to remove type keyword in constraints: https://github.com/golang/go/issues/45346

关注煎鱼,吸取他的知识

长挺丑,Go 最新的泛型类型约束语法介绍相关推荐

  1. 形容长得丑的30句经典句子

    1.长的惊险.....有创意啊! 2.你小时候被猪亲过吧? 3.你长的很爱国,很敬业,很有骨气! 4.长得真有创意,活得真有勇气! 5.你长的真tm后现代! 6.你长的好象车祸现场! 7.你长的外形不 ...

  2. 夸人长得丑的20种方法(经典)

    1. 长得惊险--. 2. 你小时候被猪亲过吧? 3. 你长得很爱国 很敬业 很有骨气 4. 你长得真有创意,活得真有勇气! 5. 你长得真TMD后现代 6. 你长得好像车祸现场 7. 你干吗用屁股挡 ...

  3. 长得丑的经典30句骂人话

    1.长的惊险.....有创意啊 2.你小时候被猪亲过吧? 3.你长的很爱国,很敬业,很有骨气! 4.长得真有创意,活得真有勇气! 5.你长的真tm后现代 6.你长的好象车祸现场 7.你长的外形不准 比 ...

  4. Banner长得丑,网站没朋友

    都说这个社会看颜值看颜值,其实网站也是看颜值的,颜值高,用户愿意多看几眼,长的丑,那就 say bye 了,当然这句话对于 12306 是不成立的. 对于网站来说,首屏 Banner 对于用户的印象很 ...

  5. 程序员都长得丑?颜值底线是程序员?

    一提到程序员妹子们第一印象是什么?加班,秃头,不修边幅,天天格子衫. 九月将近,年度最大"催肥盛典"还有几个月即将来临,不知道去年的阴影是否还停留在你们脑海,各种单身男女的日子可以 ...

  6. 长难句结构分析最新经典一百句

    <script type="text/javascript">function StorePage(){d=document;t=d.selection?(d.sele ...

  7. 长的丑的人不但没有青春,更没有爱情

    你相信爱情吗?算了,你还是问我幸福吗?我想说:长的丑的人不但没有青春,更没有爱情!低头冷眼看自己,抬头笑脸看他人,参照自己,对比他人,这样你就释怀了许多..... -----题记 青春是什么,首先青春 ...

  8. (45)System Verilog 类中变量随机激励约束语法

    (45)System Verilog 类中变量随机激励约束语法 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog 类中变量随机激励约束语 ...

  9. mysql_check_mysql CHECK约束 语法

    mysql CHECK约束 语法 作用:CHECK 约束用于限制列中的值的范围. 说明:如果对单个列定义 CHECK 约束,那么该列只允许特定的值.如果对一个表定义 CHECK 约束,那么此约束会在特 ...

最新文章

  1. SpringSession(redis)
  2. 使用E-MapReduce服务将Kafka数据导入OSS
  3. android MVP模式简介
  4. 【liferay】6、关于liferay中使用requestMapping映射地址提交表单
  5. Timeline的Animation Track详解
  6. PureCode--iOS--自定义UITableViewCell(含疑问)
  7. Ubuntu安装GoogleTest框架并测试C++代码
  8. 七乐彩中奖规则表_双色球第2020118期开奖结果出炉!你中奖了吗?
  9. MyBatis3整合Spring3、SpringMVC3
  10. 利用Keydown事件阻止用户输入
  11. 色彩原理与色彩搭配知识点回顾总结
  12. xlsxwriter去掉网格线_python之xlsxwriter模块(可操作xls/xlsx格式文件)
  13. 批量拿php webshell,剑眉大侠:批量入侵网站拿webshell挂广告引流!
  14. 邮箱手动修改服务器配置,邮箱登录手动修改服务器配置
  15. 归纳偏执_防御性编程:足够偏执
  16. Instagram API平台文档
  17. Android圆形头像图Circle ImageView
  18. B站(Bilibili) 视频的下载。
  19. 【精读文献】1 用于改进脑电图癫痫分析的自监督图神经网络
  20. 安卓基础学习 Day22|按钮的禁用与恢复

热门文章

  1. 启动NASA“造导弹”,阿里为何要“上天”?
  2. Exceeded maximum number of retries. Exceeded max scheduling attempts 3 for instance
  3. 移动应用可以通过微信沟通接口连接公众号 微信涨粉多了一个新通道
  4. 证明randomized quicksort的平均running time为nlgn 的数学过程
  5. [jvm]运行时数据区域详解
  6. 流程型企业SCM、ERP、MES、PCS如何集成?
  7. 在IOC中装配Bean
  8. 求1到N的全排列 (转载)
  9. 服务器变量:$_SERVER
  10. [转]Sublime Text 2 C++编译运行简单配置