大家好,我是炸鱼。写过几篇关于Go泛型的语法和案例介绍的文章,新的一手Go新闻。事实上,随着一些提案被采纳,新的提案也逐渐出现。不,我发现有了泛型,大家可以更进一步,取笑一下。看到一个“新”的proposal《proposal: spec: generics: type switch on parametric types》,讲的是加了泛型后对参数类型的typeswitch诉求。跟随建宇掌握围棋新知识!NewProposal新提案的内容是增加一个新的variant语句,允许在switch语句中使用泛型时进一步方便地约束类型参数。例如:switchtypeT{caseA1:caseA2,A3:...},即switch-type语句的T类型可以是泛型类型参数,case对应的类型可以是任意类型,包括通用的约束类型。假设类型T的类型可能如下:interface{CA}可以借助泛型近似元素进行约束:interface{CA1|A2|...|一个}甚至可以有case的新写法:caseinterface{~T}:支持泛型后,在类型和case上会有很多switch的可能,需要特定的feature支持。本提案就是为此目的。实战案例一:多类型元素typeStringishinterface{string|fmt.Stringer}funcConcat[SStringish](x[]S"SStringish")string{switchtypeS{casestring:...casefmt.Stringer:...}}TypeS可以支持string和fmt。Stringer类型,大小写匹配对应的实现。Case2:近似元素类型Constraintinterface{~int|?int8|~string}funcThisSyntax[TConstraint]("TConstraint"){开关类型T{case~int|~int8:...案例~string:。..}}funcIsClearerThanThisSyntax[TConstraint]("TConstraint"){开关类型T{caseinterface{~int|~int8}:...caseinterface{~string}:...}}类型T可能有很多类型,程序中用到了类似的元素,即基本类型有int、int8、string,这些中的任意一个类型可以满足此约束。为此switch-type是支持的,case也应该支持这个特性。你可能已经想到了这里的争议点。这味道很熟悉,仿佛有某种语法可以支撑似的。因此,这个提议下最具争议的是与原始类型断言的重复。原始类型断言如下:switchT.(type){casestring:...default:...}新类型区分如下:switchtypeT{caseA1:caseA2,A3:...}所以呢?乍一看,其实类型断言完全可以代替新的。那不是重复建设,造轮子吗?事实上,它并没有完全被取代。区别如下:typeApproxStringinterface{~string}funcF[TApproxString](vT"TApproxString"){switch(interface{})(v).(type){casestring:fmt.Println(v)default:panic("Thebrainisnotfriedfish")}}typeMyStringstringfuncmain(){F(MyString("Thebrainisfriedfish"))}你能看出区别吗?答案是什么?答案是:会抛出恐慌。你可能会一头雾水,问题出在哪里?传入的“脑补成炸鱼”的类型是MyString,其基本类型是string类型,也满足ApproxString类型的近似类型~string的要求。为什么不行呢...根本原因是因为它的类型是接口,不是字符串类型。所以去了默认分支的恐慌。小结今天给大家介绍了Go泛型的最新动态。上一个提案合并后,本提案有一些新的发展。不过,Go官方表示,在掌握了泛型的做法后,会继续推进提案。相信最初的switch.(type)和switchtype在Go底层很可能会被当作同一个逻辑块来处理,然后逐渐过渡。这个提案的目的是为了解决引入泛型后带来的一些bug/需求,需要新的语法结构来解决。你怎么看待这件事?欢迎在评论区留言交流:)如有问题,欢迎在评论区反馈交流。最好的关系是相互成就。您的点赞是创作炸鱼最大的动力,感谢您的支持。文章持续更新中。可以微信搜索【脑补炸鱼】阅读。本文已收录在GitHubgithub.com/eddycjy/blog中。学习Go语言可以看Go学习地图和路线。欢迎星星提醒。
