极客时间-Go实战训练营全新升级第5期无密

download:Go实战训练营全新升级第5期无密

简介

什么是泛型?

泛型编程是一种计算机编程风格,编程范式,其中算法是根据后来指定的类型编写的,然后在需要时为作为参数提供的特定类型进行实例化。常用的编程语言也基本支持泛型的这个特性,比如C++、C#、Java、Python、Rust、Swift、TypeScript、kotlin等。泛型具有以下特征:

参数化类型:类型作为函数参数传递。

  • 更强的类型检查:泛型使编译器能够在编译期间检查类型,以提高类型安全性并减少运行时由不匹配的对象类型导致的异常。
  • 代码保存和抽象表示

极客时间-Go实战训练营全新升级第5期无密_第1张图片

很长一段时间,围棋没有通用函数。参考《为什么Go语言没有泛型——面向信仰的编程》一文。这篇文章讨论了Golang不支持泛型的两个原因:

通用困境使得开发者不得不在开发效率、编译速度和运行速度之间做出选择。
目前社区里的Go语言方案都是有缺陷的,但是Go团队认为泛型的支持还不够迫切。

这篇文章认为还有另一个原因:

泛型会让Golang变得更加复杂和深远。在Go 1.18中,只提供了泛型特性,很多系统库实现都没有转换成泛型样式,泛型都是和Golang.org/x/exp库相关的。

然而,在2020年度Go开发者调查中,26%的受访者表示Go缺乏他们需要的语言功能,88%的受访者选择泛型作为关键的缺失功能。

与其他语言中的泛型相比
Go没有太多负担,但更注重设计,而Java、C++等老牌语言由于兼容性或其他原因迭代较慢。这里比较一下Go的泛型和已建立的语言泛型在语法、类型约束、实现原理等方面的区别。:

语法

去

// Go泛型泛型语法是括号。
func Print[T any](t T) {
fmt。Printf("打印类型:%T\n ",T)
}
复制代码

爪哇

公共静态无效打印(T t) {
System.out.println("打印类型:"+ t.getClass()。getName());
}
Go

// 方法限制
type Stringer interface {
   String() string
}
// 类型集合
type Types interface {
   ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 |
      ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64
}

// 限定为 Types
func  Sub[T Types](t1, t2 T) T {
   return t1 - t2
}
复制代码

Java


public class Main{
    // 泛型限定 必须是Collection 类型的子类才可以被接收
    public static  void print(T t){
        System.out.println(t);
    }

    public static void main(String[] args){
        print(Arrays.asList(1,2,3));
    }
}

实现原则

小贴士:
单一化指的是为了我们要处理的不同类型的数据而多次复制代码。单一化通常比基于继承的多态代码更快,但代价是编译时间和二进制大小。事实上,单态确保了零开销调用,而基于继承的多态需要通过虚拟调度表的间接指针。此外,编译器可以专门优化和/或内联单例代码。

提到泛型实现,Go泛型实现的一个关键特点就是只部分使用了singleton。在Go中,singleton只是部分应用了一种叫做“GC shape stenciling with dictionaries”的技术。这样做的主要效果是,指针类型或接口的所有参数都被视为属于同一个基础类型,这意味着只生成该函数的单态版本。将此与接受算术参数的函数进行比较,如int 32和float64,它们都有自己专用的函数版本。

爪哇

大多数关于Java泛型的抱怨都集中在类型擦除上。这种设计没有类型擦除。泛型类型的反射信息将包括完整的编译时类型信息。
在Java类型通配符(列表

C++

C++模板不会对类型参数施加任何约束(除非采用概念上的建议)。这意味着更改模板代码可能会意外破坏远程实例化。这也意味着只有在实例化时才会报告错误消息,并且可能嵌套很深,难以理解。这种设计通过强制和显式约束避免了这些问题。
C++支持模板元编程,可以看作是在编译时完成的普通编程,语法与非模板C++完全不同。这种设计没有类似的特点。这节省了相当大的复杂性,同时损失了一些功率和运行时效率。
++使用两阶段名称查找,其中一些名称在模板定义的上下文中找到,一些名称在模板实例化的上下文中找到。在这个设计中,所有的名字都是在书写的地方查找的。
实际上,所有C++编译器在实例化每个模板时都会编译它。这将降低编译时间。这种设计在如何处理泛型函数的编译方面提供了灵活性。

你可能感兴趣的:(go)