iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Go1.18中泛型编程的示例分析
  • 801
分享到

Go1.18中泛型编程的示例分析

2023-06-22 05:06:20 801人浏览 安东尼
摘要

小编给大家分享一下Go1.18中泛型编程的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!前言经过这几年的千呼万唤,简洁的Go语言终于在1.18版本迎来泛型

小编给大家分享一下Go1.18中泛型编程的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

前言

经过这几年的千呼万唤,简洁的Go语言终于在1.18版本迎来泛型编程。作为一门已经有了14年历史的强类型语言,很难相信它到现在才开始有一个正式的泛型。

Go1.18中泛型编程的示例分析

以前的Go泛型

虽然直到1.18版本才加入泛型,但是在2014年便有相关的讨论要在Go中加入泛型设计。但是由于各种原因没有实现。而之后的接口(interface)的提出,让泛型进一步搁置。但是由于接口的缺陷,最终Go团队还是在1.18的版本中加入了泛型。实际上,这一版本的泛型设计在语言层面和接口非常相似(在实现层面肯定是不一样的,泛型是编译时,接口是运行时),对于他们之间的差异,也会在后面提到。

本文主要讲述1.18beta1版本中的泛型,后续有改动,可能会更改文章。

泛型是什么

在我看来泛型其实用c++的模板一词来描述就非常的准确。在写代码的时候,我们经常需要写很多重复的逻辑,一般这个时候我们就会使用函数来对其进行封装。但是由于Go是一种强类型语言,所以在定义和书写函数的时候需要在调用前标明类型。当然如果这一重复的逻辑只需要固定的类型,这样就足够了,但是很多时候我们需要不同的类型进行类似的逻辑,譬如我们刚刚看到的GIF。对于普通开发人员来说这种情况可能遇到的比较少,但是在一些库开发人员来说,这种情况变得非常的普遍。

泛型程序设计(generic programming)是程序设计语言的一种风格或范式。泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。Ada、Delphi、Eiffel、Java、C#、F#、Swift 和 Visual Basic .net 称之为泛型(generics);ML、Scala 和 Haskell 称之为参数多态(parametric polymorphism);C++ 和 D称之为模板。具有广泛影响的1994年版的《Design Patterns》一书称之为参数化类型(parameterized type)。

其中,C++的模版应该是做的最完善的,不仅支持简单的模板替换,还可以处理一些简单的逻辑,经过不断的迭代,已经形成了一种生成代码的编程方式,因此也叫做模板元编程(Template metaprogramming)。当然由于其和C++编程方式完全不一致,所以可读性非常的差。而在Go的泛型设计中,为了保证泛型的简洁,Go并不支持模版元编程(心塞,还想试试在Go里面往往骚操作呢)。

Go的泛型

接下来就是Go泛型的使用介绍了,Go支持泛型函数和泛型类型。

泛型函数

先来一个最简单的泛型函数

func ink19FirstGen[T any](t T) { fmt.Println(t)}

这是一个非常简单的的函数,就是使用fmt.Println打印输入的参数。相比于以前的函数,多了[T any]部分,这就是Go泛型的参数列表。

参数列表中的参数由两部分组成,参数名和约束,其中T就是参数,any为参数的约束。从表达上来说,和Go语言一贯的风格相似,名在前,类型在后。

在Go语言中,使用接口interface做为类型的约束,其中any = interface{},即为无限制,但是以其说是无限制,倒不如说是完全限制,由于any里面没有定义任何的方法,所以在函数里面也没办法调用t的任何方法。

这里有一个非常重要的问题,就是相比较于C++的模板,Go会在定义函数的时候就对函数进行解析。所以在函数中使用了的方法,一定要在约束的接口中出现。

type ink19Inf interface { Test()}func ink19FirstGen[T ink19Inf](t T) { t.Test()}

和普通参数类似的,如果是相同的约束,参数类型也支持简化

func ink19FirstGen[T ,T2 ink19Inf](t T, t2 []T2) { t.Test()}

泛型类型

和C++中的模板类类似的,Go里面也有泛型类型,它的定义也很简单

type ink19Vector[T any] []T

结构相比与以前的类型定义多了[T any]部分,这一部分的结构和泛型函数那一部分类似就不多介绍了。

对于泛型类型,Go也可以定义相关的方法,譬如:

func (m *ink19Vector[T]) Push(v T) *ink19Vector[T] { *m = append(*m, v) return m}

在泛型结构体中,结构体也可以定义自己的类型的变量,形成链表

type List[T1, T2 any] struct { next *List[T1, T2] t1 T1 t2 T2}

PS:依据提案中的说法,第二行的参数列表应该和定义中的顺序一致,以防止无限递归。但是在1.18beta1版本的实测中,顺序不一致的写法并不会报错。

Go暂时不支持方法的泛型。

类型集合

虽然通过接口限制类型可以满足绝大部分的要求,但是仍然有一些需求满足不了,譬如运算符。假如我们有一个函数,可以传入任意可比较的参数,然后返回较小的那一个。很自然的,我们可以写下如下的代码:

func whoismin[T any](a, b T) T {  if a < b {    return a  }  return b}

但是,很遗憾的,由于我们对T的约束是any。所以其实来说,我们没办法对a和b做任何的操作,对比也是。所以在这里,我们会收到报错

invalid operation: cannot compare a < b (operator < not defined on T)

为了解决这一问题,提案中提出了类型集合的概念。

对于一个类型,认为它代表的类型集合就是只包含这个类型的集合,即对于类型M来说,其代表的类型集合为{M}。而对于接口来说,其对应的类型集合是无限的,只要一个类型满足接口的所有方法签名,那么这个类型就是属于这个接口的类型集合中。其实很容易理解类型集合就是那个识别符可以代表的类型的集合。

考虑集合的操作,对于下面这个例子

type ink19Inf1 interface { What1()}type ink19Inf2 interface { What2()}type ink19Inf3 interface { What1() What2()}

假设ink19Inf1的类型集合为A,ink19Inf2的为B,ink19Inf3的为C。那么很容得到C=A⋂B。即C为A和B的交集。当然只有交集是不行的,后面还有说明实现并集。

为了进一步的说明类型集合,我们先来回忆一下接口的定义,对于之前的接口来说,接口的元素一共有两种:方法签名和其他接口。

type ink19Inf1 interface { What()}type ink19Inf2 interface { ink19Inf1 It()}

比如ink19Inf2中的第一个元素就是其他接口,第二个元素是其他签名。但是仅仅只是有这两种元素,对于泛型约束来说是完全不够的。为此,提案中加入了另外三种不同的元素,需要注意的是,如果一个接口加入了这额外三种元素,那么这个接口就不能再作为普通的接口使用了,只能用作泛型。

第一个增加的是类型元素。以前的接口是不能用类型作为接口的,但是在作为约束中可以这样操作。作为元素的时候就是提供了一个只包含自己本身的类型作为元素的类型集合。

第二个是增加了近似约束元素,写法是在类型前面增加~符号,如

type ink19Inf1 interface { ~int}

这一个元素的意义是为接口提供了一个所有以int为底层类型的集合。所以被~修饰的类型也应该是一个底层类型,不然提供的集合就是空集,没有任何意义。具体的区别可以看下面的这个例子。

type ink19Inf3 interface { int}type ink19Inf4 interface { ~int}type MyInt int

首先我们定义了两个接口,第一个接口使用的是额外的第一种元素, 因此它的类型集合只包含了int。另一个使用了第二种元素,它的类型集合包含了所有以int为底层类型的类型。然后我们定义了一个MyInt类型,它是以int为底层类型的类型。需要注意的是,在Go中MyInt和int是两种不同的类型。最后我们写两个方法来分别使用两个接口为约束。

func ink19Print1[T ink19Inf3](t T) { fmt.Println(t)}func ink19Print2[T ink19Inf4](t T) { fmt.Println(t)}var data MyInt = 1ink19Print1(data)  // 错误ink19Print2(data)

第三个元素是联合约束。使用方法如下

type ink19Inf5 interface { int | float32 | bool | ~string | ink19Inf3}

使用方法非常简单,就是将并集的元素一个一个使用|连接就就好了。需要注意的是联合约束的元素只支持类型,近视约束和其他只包含以上三种额外元素的接口(即,不支持包含方法签名的接口)。

回到之前的问题,对于需要使用操作符的情况,有了以上的工具后就可以解决了。

纵观整个Go语言,由于并不支持操作符,所以有操作符(除了==和!=)的其实只有有限的几种类型,譬如:int,float32,string等等。

所以对于需要使用比较运算符的约束的时候,可以使用如下的一个约束接口:

type Ordered interface { ~int | ~int8 | ~int16 | ~int32 | ~int64 |  ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |  ~float32 | ~float64 |  ~string}

为了方便使用,Go标准库里面提供了一个constraints来提供相关的约束。

上面提到,对于除了==和!=以外的操作符可以通过对所有的类型进行枚举来实现。但是对于这两个操作符,用户自定义的类型也会有这两个操作符,没办法枚举实现。官方给出的方法是通过使用一个一个内建的约束comparable来完成操作。譬如

func IsSame[T comparable](a T, b T) bool { return a == b}

和接口的差异

由于本人对于Go的接口使用并不多,所以如果有不足的地方请及时指正。

  • 实现方法上,泛型是编译时,接口是运行时;

  • 可以实现操作符的约束;

  • 返回的参数可以是特定的类型,而接口只能返回固定的接口类型;

  • 相比较于接口,泛型的约束可以有更多的操作。

以上是“Go1.18中泛型编程的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网精选频道!

--结束END--

本文标题: Go1.18中泛型编程的示例分析

本文链接: https://www.lsjlt.com/news/302965.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Go1.18中泛型编程的示例分析
    小编给大家分享一下Go1.18中泛型编程的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!前言经过这几年的千呼万唤,简洁的Go语言终于在1.18版本迎来泛型...
    99+
    2023-06-22
  • Go1.18新特性之泛型实例代码分析
    本篇内容主要讲解“Go1.18新特性之泛型实例代码分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Go1.18新特性之泛型实例代码分析”吧!1. 一切从函数的形参和实参说起假设我们有个计算两数...
    99+
    2023-07-05
  • Java中泛型的示例分析
    小编给大家分享一下Java中泛型的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1. 为什么使用泛型早期的Object类型可以接收任意的对象类型,但是在实...
    99+
    2023-06-20
  • Java中泛型擦除的示例分析
    小编给大家分享一下Java中泛型擦除的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1.问题引出源码: public static&n...
    99+
    2023-05-31
    java
  • Java中泛型与通配符的示例分析
    这篇文章主要介绍Java中泛型与通配符的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!题外话: 泛型与通配符是Java语法中比较难懂的两个语法,学习泛型和通配符的主要目的是能够看懂源码,实际使用的不多。1.泛...
    99+
    2023-06-29
  • java泛型数组转换类型的示例分析
    小编给大家分享一下java泛型数组转换类型的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!java基本数据类型有哪些Java的基本数据类型分为:1、整数类型,用来表示整数的数据类型。2、浮点类型,用来表示小数的数据...
    99+
    2023-06-14
  • LINQ查询基于泛型类型的示例分析
    小编给大家分享一下LINQ查询基于泛型类型的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!LINQ查询基于泛型类型,在 .NET Framework 的 ...
    99+
    2023-06-17
  • Java泛型实例分析
    这篇文章主要介绍“Java泛型实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java泛型实例分析”文章能帮助大家解决问题。首先,我们来看看泛型Java的经典用法:import java.ut...
    99+
    2023-06-03
  • PHP中的泛型使用实例分析
    这篇文章主要介绍“PHP中的泛型使用实例分析”,在日常操作中,相信很多人在PHP中的泛型使用实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”PHP中的泛型使用实例分析”的疑惑有所帮助!接下来,请跟着小编...
    99+
    2023-06-30
  • PHP中SOCKET编程的示例分析
    这篇文章主要介绍了PHP中SOCKET编程的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1. 预备知识一直以来很少看到有多少人使用php的socket模块来做一些事...
    99+
    2023-06-15
  • udp编程的示例分析
    小编给大家分享一下udp编程的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!什么是UDPUDP是User Datagram Protocol(用户数据报协...
    99+
    2023-06-27
  • CSS中的层分离编程示例分析
    本篇文章为大家展示了CSS中的层分离编程示例分析,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。随着CSS的发展,使用CSS有语义化的命名约定和CSS层的分离,将有助...
    99+
    2024-04-02
  • C# 泛型实现的实例分析
    这期内容当中小编将会给大家带来有关C# 泛型实现的实例分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。C# 泛型实现在 .NET 2.0 中,C# 泛型在 IL(中间语言)和 CLR 本身中具有本机支持...
    99+
    2023-06-17
  • Promise中异步编程的示例分析
    这篇文章主要介绍Promise中异步编程的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!实例如下所示://1.解决异步回调问题 //1.1 如何同步异步请求 //如...
    99+
    2024-04-02
  • JavaScript中异步编程的示例分析
    这篇文章给大家分享的是有关JavaScript中异步编程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。目的提升开发效率,编写易维护的代码引子问题请求时候为什么页面卡死??$.ajax({ &n...
    99+
    2023-06-15
  • c#中异步编程的示例分析
    这篇文章给大家分享的是有关c#中异步编程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、什么算异步?  广义来讲,两个工作流能同时进行就算异步,例如,CPU与外设之间的工作流就是异步的。在面向服务的系...
    99+
    2023-06-14
  • Java泛型使用实例分析
    本篇内容主要讲解“Java泛型使用实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java泛型使用实例分析”吧!1.概述作为一个面向对象的编程语言,Java可以通过实现一些类,作为我们各种...
    99+
    2023-06-29
  • golang泛型编程的实用案例
    Golang泛型编程的实际应用案例,需要具体的代码示例 引言:随着云计算、大数据和人工智能的发展,软件开发工程师面临的挑战日益增加。编程语言的泛型特性能够提供更高效、更灵活的解决方案,而Golang作为一门现...
    99+
    2024-01-20
    Golang 案例 实际应用 泛型编程
  • Java基础泛型实例分析
    这篇“Java基础泛型实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java基础泛型实例分析”文章吧。一、泛型概述:...
    99+
    2023-06-29
  • Java中泛型的示例详解
    目录泛型概述使用泛型的好处泛型的定义与使用定义和使用含有泛型的类含有泛型的方法含有泛型的接口泛型通配符通配符基本使用通配符高级使用----受限泛型泛型概述 我们都知道集合中是可以存放...
    99+
    2022-11-13
    Java泛型机制 Java泛型
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作