广告
返回顶部
首页 > 资讯 > 后端开发 > GO >Golang中的泛型你真的了解吗
  • 700
分享到

Golang中的泛型你真的了解吗

Golang泛型用法Golang泛型学习Golang泛型Go 泛型 2023-05-20 06:05:33 700人浏览 独家记忆
摘要

目录什么是泛型为什么需要泛型泛型语法类型参数类型集类型推断总结golang 在 1.18 版本更新后引入了泛型,这是一个重要的更新,Gopher 万众瞩目,为 Golang 带来了更

golang 在 1.18 版本更新后引入了泛型,这是一个重要的更新,Gopher 万众瞩目,为 Golang 带来了更多的灵活性和可重用性,同时也解决了在特定场景下 Golang 类型系统的限制。

今天,我们将深入探讨泛型的概念、为什么需要泛型、泛型的语法,并探讨如何在实践中使用它。

go version >= 1.18

什么是泛型

泛型是一种在软件开发中广泛使用的编程概念,它允许开发者编写可重用的代码,而不需要考虑具体的数据类型。使用泛型,开发者可以编写一些通用的算法数据结构,这些算法和数据结构可以适用于不同类型的数据,而不需要为每种类型都编写一份专用的代码。泛型的概念在其他许多编程语言中都有支持,比如 c++、Java、C# 等。

为什么需要泛型

假设我们需要实现一个返回一个 Map key 的 切片 []int -- MapKeysToInt。

func MapKeysToInt(m map[int]string) []int {
	r := make([]int, 0, len(m))
	for k := range m {
		r = append(r, k)
	}
	return r
}

可是这个函数只能接收map[int]string 类型的参数,如果我们想支持 int8 类型的参数,我们就需要再定义一个MapKeysToInt8 函数。

func MapKeysToInt8(m map[int8]string) []int8 {
	r := make([]int8, 0, len(m))
	for k := range m {
		r = append(r, k)
	}
	return r
}

如果要想支持 int64 类型切片就要定义 MapKeysToInt32 函数,如果想支持 xxx 就需要定义一个 MapKeysToXXX...

我们会发现一遍一遍地编写相同的功能非常的低效,

func MapKeysToInt32(m map[int32]string) []int32 {
	r := make([]int32, 0, len(m))
	for k := range m {
		r = append(r, k)
	}
	return r
}

Go1.18 之前我们可以使用反射的方式去实现上述问题,但是会降低代码的执行效率且失去编译期的类型检查等弊端。

Go1.18 之后我们可以用泛型来实现这一系列问题,eg:

// 当调用泛型函数的时候, 我们经常可以使用类型推断。 
// 注意,当调用 MapKeys 的时候,我们不需要为 K 和 V 指定类型 - 编译器会进行自动推断
func MapKeys[K comparable, V any](m map[K]V) []K {
	r := make([]K, 0, len(m))
	for k := range m {
		r = append(r, k)
	}
	return r
}

func main (){
	var m = map[int]string{
		1: "2",
		2: "4",
		4: "8",
	}
	fmt.Println("keys m:", MapKeys(m))

    var m2 = map[string]int{
		"程序员祝融": 1,
		"李四": 2,
		"王五": 3,
	}
	fmt.Println("keys m2:", MapKeys(m2))
}

// demo 运行结果:
// keys m: [2 4 1]
// keys m2: [李四 王五 程序员祝融]

泛型语法

泛型为Go语言添加了三个新的重要特性:

  • 类型参数(形参、实参)
  • 类型集
  • 类型推断

类型参数

之前我们定义函数时可以指定其形参,调用函数时传实参,如下。

现在,Go 语言中的函数和类型支持添加类型参数。类型参数以类似于函数参数的方式进行定义,使用方括号 [] 包含一个或多个类型参数。

用泛型实现一个比较两数大小的 demo ,eg:

func max[T int | int32 | int64 | float32](x, y T) T {
	if x >= y {
		return x
	}
	return y
}

类型实例化

我们定义了一个 max 函数,支持传 int、int32、int64、float32 类型,我们可以传入这 4 种类型中的任意一个。 eg 传一个 int 类型:

max[int32](1, 2) // 2

也支持传一个 float32 类型:

max[float32](0.1, 0.2) // 0.2

max 函数提供类型参数(在本例中为 int 和float32 ) 称为实例化。eg:

// 类型实例化,编译器生成 T=float32 的 max 函数
f := max[float32]
fmt.Println(f(0.1, 0.2))

我们定义了一个 max[float32] 函数 f,我们可以在接下来调用函数的方式使用 f(0.1, 0.2) 它 。

类型约束

类型约束是指限制类型参数的类型的约束条件,可以使用interface关键字来表示。以上方的 demo,我们常见的方式有:

类型约束接口直接在类型参数列表中使用:

func max[T interface{ int | int32 | int64 | float32 }](x, y T) T {
	if x >= y {
		return x
	}
	return y
}

也可以事先定义,后复用

// 事先定义类型约束类型
type Value interface {
	int | int32 | int64 | float32 
}
func min[T Value](a, b T) T {
	if a <= b {
		return a
	}
	return b
}

在定义一个可以比较大小的泛型函数时,可以使用 comparable约束条件来限制类型参数的类型:

func MapKeys[K comparable, V any](m map[K]V) []K {
	r := make([]K, 0, len(m))
	for k := range m {
		r = append(r, k)
	}
	return r
}

类型集

类型集是泛型语法中用来约束类型参数的工具,它规定了类型参数所能接受的类型范围。在 Golang 1.18 中,类型集使用 interface 来定义,在类型参数后面添加 interface 关键字来实现的。通俗一点解释,接口类型现在可以用作值的类型,也可以用作类型约束。

下面是一个定义了类型集的例子:

type MySlice interface {
	int | float32 | string
}

上面这个就表示定义了一个 int、float32、string 的类型集。

any 接口

Go 在 1.18 引入了一个新的预声明标识符,作为空接口类型的别名。

type any = interface{}

使用 eg:

func Swap[T any](a, b *T) {
    temp := *a
    *a = *b
    *b = temp
}

类型推断

最后说下类型推断,非常重要,在go 1.18 后推出,能够让开发者在使用泛型时更加的自然。

参数类型推断

对于函数参数的类型,需要传递类型参数,使得代码变长。看下一开始的 demo

func max[T int | int32 | int64 | float32](x, y T) T {
	if x >= y {
		return x
	}
	return y
}

调用

var a, b, s int
a := 1
b := 2
s := max[int32](a, b) // 2

在大部分场景下,我们的编译器其实可以自行推断类型参数 T。有了这个可以似的我们的代码变的更短,同事保持清晰。

var a, b, s int
a := 1
b := 2
s := max(a, b) // 2

总结

Go 在 1.18 中引入了泛型这一特性,极大地增强了语言的表现力和灵活性。通过类型参数、类型集、类型推断等语法特性,可以方便地定义和使用泛型类型和泛型函数。同时,编译器对泛型的支持也在不断完善,包括对类型参数的约束、类型集的多态和类型推断的增强等,进一步提升了泛型的实用性和性能。

在实际开发中,泛型可以用来处理许多常见的问题,如集合类的封装、算法的实现和通用接口的定义等。除了标准库中已经实现的泛型类型和函数之外,我们还可以通过自定义泛型类型和函数来满足特定的需求。

最后,使用泛型时需要注意类型安全和性能问题,特别是对于大规模的数据处理和算法计算,需要进行细致的测试优化

到此这篇关于Golang中的泛型你真的了解吗的文章就介绍到这了,更多相关Golang泛型内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

本文标题: Golang中的泛型你真的了解吗

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

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

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

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

下载Word文档
猜你喜欢
  • Golang中的泛型你真的了解吗
    目录什么是泛型为什么需要泛型泛型语法类型参数类型集类型推断总结Golang 在 1.18 版本更新后引入了泛型,这是一个重要的更新,Gopher 万众瞩目,为 Golang 带来了更...
    99+
    2023-05-20
    Golang泛型用法 Golang泛型学习 Golang泛型 Go 泛型
  • java的泛型你真的了解吗
    目录泛型的概述和优势自定义泛型类自定义泛型方法自定义泛型接口泛型通配符、上下限总结泛型的概述和优势 泛型概述 泛型:是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检...
    99+
    2022-11-13
  • Python 中的单分派泛函数你真的了解吗
    泛型,如果你学过Java ,应该对它不陌生吧。但你可能不知道在 Python 中(3.4+ ),也可以实现简单的泛型函数。 在Python中只能实现基于单个(第一个)参数的数据类型来...
    99+
    2022-11-12
  • TypeScript中的接口和泛型你了解吗
    目录接口对象类型索引类型函数类型继承交叉类型接口实现interface 和 type 的区别字面量赋值枚举类型泛型泛型函数泛型接口泛型类类型约束总结接口 使用 interface 关...
    99+
    2022-11-13
  • C++的数据类型你真的了解吗
    目录前言1 整型2 sizeof关键字3 实型(浮点型)4 字符型5 转义字符6 字符串型7 布尔类型 bool8 数据的输入总结前言 C++不像python,创建变量的时候必须指定...
    99+
    2022-11-13
  • Go语言的泛型是真泛型吗
    Go语言的泛型在设计上并不是真正的泛型。在其他编程语言中,泛型通常指的是可以在函数或数据结构中使用不特定类型的能力。然而,Go语言的...
    99+
    2023-10-12
    Go语言
  • 你真的了解Go语言中的数据类型吗?
    Go语言作为一门静态类型语言,数据类型是其非常重要的组成部分。熟悉Go语言中的数据类型,能够更好地理解和使用该语言。本文将带大家了解Go语言中的常用数据类型。 基本数据类型 Go语言中的基本数据类型包括bool、int、float、comp...
    99+
    2023-07-03
    数据类型 npm 框架
  • 深入了解golang中的的泛型(Generic)
    本篇文章给大家带来的内容是介绍深入理解golang中的泛型?泛型怎么使用?有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所助。什么是泛型泛型(Generic)是一种编程技术。在强类型语言中, 允许编写代码时使用以后才指定的类型, ...
    99+
    2023-05-14
    Go 后端
  • PHP接口中的数据类型:你真的理解了吗?
    当我们在进行 PHP 接口开发时,数据类型是一个非常重要的概念。虽然我们在学习编程的时候都会学习到数据类型这个概念,但是在实际开发中,我们有时候可能并没有真正理解数据类型的概念,也不知道如何正确使用它们。因此,在本文中,我们将深入探讨 PH...
    99+
    2023-06-01
    接口 学习笔记 数据类型
  • 你真的了解IP地址吗?
    本文已收录于专栏 ⭐️ 《计算机网络》⭐️ 学习指南: IP协议基本认识分类地址多播地址 无分类地址划分方式子网掩码 IP 分片与重组IPv6基本认识IPv4 首部与 ...
    99+
    2023-09-09
    tcp/ip 网络 服务器 网络协议 ip
  • 你真的需要了解Bash吗?
    Bash是一种强大的命令行解释器,它是Linux和macOS操作系统上的默认Shell。尽管它是如此重要,但很多人并不了解Bash的实际用途。在本文中,我们将探讨Bash的重要性以及它如何帮助我们更好地管理和控制计算机系统。 Bash是什么...
    99+
    2023-08-15
    path bash http
  • 关于Java Object你真的了解了吗
    导读: 在平时的coding中hashCode()和equals()的使用的场景有哪些?clone深复制怎么实现?wait()和notify()有什么作用?finalize()方法干嘛的?看似coding中使用的不多,不重要,但是有没有跟我...
    99+
    2023-05-31
    java object ava
  • C++中的函数你真的理解了吗
    目录1 概述2 函数的定义及调用3 值传递4 函数的常见形式5 函数的声明6 函数的分文件编写作用:让代码结构更加清晰1.2.3.4.总结1 概述 作用:将一段经常使用的代码进行封装...
    99+
    2022-11-13
  • C++中的数组你真的理解了吗
    目录1 概述2 一维数组2.1 一维数组定义方式2.2 一维数组组名2.3 冒泡排序3 二维数组3.1 二维数组定义方式3.2 二维数组数组名3.3二维数组应用举例总结1 概述 所谓...
    99+
    2022-11-13
  • python3中的类继承你真的了解吗
    目录(1)首先使用直接继承的方式(2)在子类中定义属性(3)如果想要继承父类中的属性,一般使用super方法:(4)如果需要在子类的__init__中传入参数则可以这样使用:&nbs...
    99+
    2022-11-13
  • 一文带你深入理解Golang中的泛型
    目录1. 概述1.1 什么是泛型1.2 Go 泛型的背景1.3 Go 泛型的特点2. 语法2.1 泛型函数2.2 泛型类型2.3 泛型约束2.4 泛型特化2.5 泛型接口2.5.1 ...
    99+
    2023-05-18
    Golang泛型用法 Golang泛型 Go 泛型
  • C语言的模板与泛型编程你了解吗
    目录模板与泛型编程浅谈摘要(Effective C++):模板与泛型编程简单介绍函数模板模板编译类模板为什么我们需要模板特例化?总结模板与泛型编程浅谈 摘要(Effective C+...
    99+
    2022-11-13
  • 你真的了解PHP数据类型的存储方法吗?
    PHP作为一种脚本语言,拥有着丰富的数据类型。在PHP中,数据类型的存储方法对于程序的性能和可读性都有着重要的影响。本文将介绍PHP数据类型的存储方法,并通过一些演示代码来展示它们的用法。 一、PHP数据类型的基本介绍 在PHP中,数据类型...
    99+
    2023-10-16
    数据类型 存储 教程
  • 关于@Autowierd && @Resource 你真的了解吗
    目录关于@Autowierd && @Resource 你真的了解吗1.@Autowierd2.@Resource2.1@Resource具体装配顺序,即指定的注入实...
    99+
    2022-11-12
  • Vue的过滤器你真了解吗
    目录1.过滤器1.1对过滤器的理解1.2全局过滤器:1.3局部过滤器:1.4过滤器的案例总结1. 过滤器 案例中使用到时间格式相关API 1.1 对过滤器的理解 定义:对要显示的数据...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作