本文转载自微信公众号《我的脑子是炸鱼》,作者陈建宇。转载本文请联系脑筋急转弯公众号。大家好,我是炸鱼。写过几篇关于Go泛型的语法和案例介绍的文章,新的一手Go新闻。事实上,随着一些提案被采纳,新的提案也逐渐出现。不,我发现有了泛型,大家可以更进一步,取笑一下。看到一个“新”的proposal《proposal: spec: generics: type switch on parametric types[1]》,讲的是加了泛型后对参数类型的typeswitch诉求。和建宇一起掌握围棋新知识!新提案新提案是增加一个新的variant语句,允许在switch语句的类型中使用泛型来进一步方便地约束其类型参数。例如:switchtypeT{caseA1:caseA2,A3:...},即switch-type语句的T类型可以是泛型类型参数,case对应的类型可以是任意类型,包括泛型约束类型。假设类型T的类型可能是下面的类型:interface{CA}可以借助通用的近似元素来约束:interface{CA1|A2|...|An}甚至可以有新的写法以防万一:caseinterface{~T}:支持泛型后,在type和case方面会有很多switch的可能,需要特定的feature支持。本提案就是为此目的。实战案例一:多类型元素typeStringishinterface{string|fmt.Stringer}funcConcat[SStringish](x[]S"SStringish")string{switchtypeS{casestring:...casestring:...casefmt.Stringer:...}}TypeScan支持string和fmt.Stringer类型,大小写匹配对应的实现。情况2:近似元素typeConstraintinterface{~int|~int8|~string}funcThisSyntax[TConstraint]("TConstraint"){switchtypeT{case~int|~int8:...case~string:...}}funcIsClearerThanThisSyntax[TConstraint]("TConstraint"){switchtypeT{caseinterface{~int|~int8}:...caseinterface{~string}:...}}类型T可能有很多种,程序中使用了类似的元素,其中基本类型是int、int8、string,这些类型中的任何一个都可以满足这个约束。为此switch-type是支持的,case也应该支持这个特性。你可能已经想到了这里的争议点。这味道很熟悉,仿佛有某种语法可以支撑似的。因此,这个提议下最具争议的是与原始类型断言的重复。原来的类型断言如下:switchT.(type){casestring:...default:...}新的类型区分如下:switchtypeT{caseA1:caseA2,A3:...}所以乍一看,其实类型断言Thenewones完全可以替代newones,那岂不是重复建设,重新造轮子?事实上,它并没有被完全取代。区别如下:typeApproxStringinterface{~string}funcF[TAApproxString](vT"TAApproxString"){switch(interface{})(v).(type){casestring:fmt.Println(v)default:panic("brain没有输入Friedfish")}}typeMyStringstringfuncmain(){F(MyString("Mybrainisfriedfish"))}你能看出区别吗?答案是什么?答案是:会抛出恐慌。你可能会一头雾水,问题出在哪里?传入的“脑炸鱼”的类型是MyString,其基本类型是string类型,也满足ApproxString类型的近似类型~string的要求。为什么它不起作用?...根本原因是因为他的类型是接口,而不是字符串类型。所以去了默认分支的恐慌。小结今天给大家介绍一下关于Go泛型的最新消息。上一个提案合并后,本提案有一些新的发展。不过,Go官方表示,在掌握了泛型的做法后,会继续推进提案。相信最初的switch.(type)和switchtype在Go底层很可能会被当作同一个逻辑块来处理,然后逐渐过渡。这个提案的目的是为了解决引入泛型后带来的一些bug/需求,需要新的语法结构来解决。对此你怎么看,欢迎在评论区留言交流:)参考[1]提案:spec:generics:typeswitchonparametrictypes:https://github.com/golang/go/issues/45380
