iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > GO >详解如何利用Golang泛型提高编码效率
  • 356
分享到

详解如何利用Golang泛型提高编码效率

Golang泛型提高编码效率Golang泛型提高效率Golang 泛型 2023-05-14 08:05:12 356人浏览 薄情痞子
摘要

目录前言工具函数数据结构模板代码对象池/缓存总结前言 golang的泛型已经出来有一段时间了,大家应该或多或少对它有所了解,甚至已经在应用中使用它。虽然Golang的泛型在功能上确实

前言

golang的泛型已经出来有一段时间了,大家应该或多或少对它有所了解,甚至已经在应用中使用它。虽然Golang的泛型在功能上确实比较简单,而且确实可能会增加代码的复杂度,过度使用可能还会降低代码可读性。

但不可否认泛型确实让我们在使用Golang的时候能够抽取一些通用的代码,避免代码的重复拷贝,提高代码性能(避免类型转换),提高编码的效率和体验,提高代码可维护性。

这篇文章主要是介绍我使用Golang泛型做过的事情。

工具函数

虽然标准库里面已经提供了大量的工具函数,但是这些工具函数都没有使用泛型实现,为了提高使用体验,我们可以使用泛型进行实现。

比如数值算法里很经典的math.Max()math.Min()都是float64类型的,但是很多时候我们使用的是intint64这些类型,在Golang引入泛型之前,我们经常像下面这样根据类型实现,产生大量模板代码:

func MaxInt(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func MaxInt64(a, b int64) int64 {
	if a > b {
		return a
	}
	return b
}

// ...其他类型

而使用泛型则我们只需要一个实现:

func Max[T constraints.Ordered](a, b T) T {
	if a > b {
		return a
	}
	return b
}

其中constraints.Ordered表示可排序类型,也就是可以使用三路运算符的类型[>, =, <],包含了所有数值类型和string。可以通过go get golang.org/x/exp引入。

代码地址

其他的像JSON解析、参数校验、slices等也可以通过泛型进行实现。

数据结构

Golang自带的泛型容器有slices和map,这两个数据结构其实可以完成大部分工作了,但是有时候我们可能还需要其他的数据结构,比如说优先级队列、链表等。

虽然Golang在container包下有heaplistring三个数据结构,但说实话使用起来不是很方便,特别是元素类型全是interface{},使用这些结构就需要各种类型转换。因此我们可以简单的拷贝这些代码,然后使用泛型进行改造,比如heap:

我们不但使用泛型进行实现,还把heap默认改为使用slice是实现,这样只需要实现一个LessFunc,而不是5个。

package heap

type LessFunc[T any] func(e1 T, e2 T) bool

type Heap[T any] struct {
	h        []T
	lessFunc LessFunc[T]
}

func New[T any](h []T, lessFunc LessFunc[T]) *Heap[T] {
	heap := &Heap[T]{
		h:        h,
		lessFunc: lessFunc,
	}
	heap.init()
	return heap
}

// 移除堆顶元素
func (h *Heap[T]) Pop() T {
	n := h.Len() - 1
	h.swap(0, n)
	h.down(0, n)
	return h.pop()
}

// 获取堆顶元素
func (h *Heap[T]) Peek() T {
	return h.h[0]
}

// 添加元素到堆
func (h *Heap[T]) Push(x T) {
	h.push(x)
	h.up(h.Len() - 1)
}

代码地址

其他的数据结构还包括list、set、pqueue等。

模板代码

在后台业务代码里面,我们经常会有很多个业务处理函数,每个业务处理函数我们基本都会通过一些代码封装成一个Http接口,这里其实基本上都是模板代码,比如说对于一个使用gin实现的HTTP服务,每个接口我们都需要进行以下处理:

  • 指定HTTP方法、URL
  • 鉴权
  • 参数绑定
  • 处理请求
  • 处理响应

可以发现,参数绑定、处理响应几乎都是一样模板代码,鉴权也基本上是模板代码(当然有些鉴权可能比较复杂)。

因此我们可以编写一个泛型模板,把相同的部分抽取出来,用户只需要实现不同接口有差异的指定HTTP方法、URL和处理请求逻辑即可:

// 处理请求
func do[Req any, Rsp any, Opt any](reqFunc ReqFunc[Req],
	serviceFunc ServiceFunc[Req, Rsp], serviceOptFunc ServiceOptFunc[Req, Rsp, Opt], opts ...Opt) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 参数绑定
		req, err := BindjsON[Req](c)
		if err != nil {
			return
		}
		// 进一步处理请求结构体
		if reqFunc != nil {
			reqFunc(c, req)
		}
		var rsp *Rsp
		// 业务逻辑函数调用
		if serviceFunc != nil {
			rsp, err = serviceFunc(c, req)
		} else if serviceOptFunc != nil {
			rsp, err = serviceOptFunc(c, req, opts...)
		} else {
			panic("must set ServiceFunc or ServiceFuncOpt")
		}
		// 处理响应
		ProcessRsp(c, rsp, err)
	}
}

这样,现在一个接口基本上只需要一行代码即可实现(不包括具体业务逻辑函数):

	// 简单请求,不需要认证
	e.GET("/user/info/get", ginrest.Do(nil, GetUserInfo))
	// 认证,绑定UID,处理
        reqFunc := func(c *gin.Context, req *UpdateUserInfoReq) {
		req.UID = GetUID(c)
	} // 这里拆多一步是为了显示第一个参数是ReqFunc
	e.POST("/user/info/update", Verify, ginrest.Do(reqFunc, UpdateUserInfo))

代码地址,实现了一个基于gin的RESTful风格模板。

对象池/缓存

Golang标准库自带了一个线程安全、高性能、还能够根据对象热度自动进行释放的对象池sync.Pool,然而作为对象池,我们一般只会往里面放一种类型的对象,但sync.Pool里面的元素还是interface{}类型,因此我们可以简单的封装sync.Pool,让它里面的元素有具体类型:

这里其实就是简单的对象sync.Pool进行包装,然后添加了一个ClearFunc()在回收对象的时候进行一些清理操作,比如说byte切片我们需要让它的已用长度归零(容量还是不变)。

// 创建新对象
type NewFunc[T any] func() T

// 清理对象
type ClearFunc[T any] func(T) T

type Pool[T any] struct {
	p         sync.Pool
	clearFunc ClearFunc[T]
}

func New[T any](newFunc NewFunc[T], clearFunc ClearFunc[T]) *Pool[T] {
	if newFunc == nil {
		panic("must be provide NewFunc")
	}
	p := &Pool[T]{
		clearFunc: clearFunc,
	}
	p.p.New = func() any {
		return newFunc()
	}
	return p
}

// 获取对象
func (p *Pool[T]) Get() T {
	return p.p.Get().(T)
}

// 归还对象
func (p *Pool[T]) Put(t T) {
	if p.clearFunc != nil {
		t = p.clearFunc(t)
	}
	p.p.Put(t)
}

作为字节数组对象池使用:

	newFunc := func() []byte {
		return make([]byte, size, cap)
	}
	clearFunc := func(b []byte) []byte {
		return b[:0]
	}
	p := New(newFunc, clearFunc)
	bytes := p.Get() // 这里bytes类型是[]byte
	p.Put(bytes)

代码地址

对于缓存也是同理,目前大部分缓存库的实现都是基于interface{}或者是byte[],但是我们还是更加喜欢直接操作具体类型,因此我们可以自己使用泛型实现(或改造)一个缓存库。我自己也实现了一个泛型缓存策略库,里面包含LRU、LFU、ARC、NearlyLRU、TinyLFU等缓存策略。

总结

可以看到,其实Golang泛型主要提供了一种代码抽象、封装的能力,让我们能够写出更能复用的代码,避免代码到处拷贝,从而能够提高代码的可维护性,可读性,还能从避免类型转换中得到一点性能提升。

到此这篇关于详解如何利用Golang泛型提高编码效率的文章就介绍到这了,更多相关Golang泛型内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

本文标题: 详解如何利用Golang泛型提高编码效率

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

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

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

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

下载Word文档
猜你喜欢
  • 详解如何利用Golang泛型提高编码效率
    目录前言工具函数数据结构模板代码对象池/缓存总结前言 Golang的泛型已经出来有一段时间了,大家应该或多或少对它有所了解,甚至已经在应用中使用它。虽然Golang的泛型在功能上确实...
    99+
    2023-05-14
    Golang泛型提高编码效率 Golang泛型提高效率 Golang 泛型
  • 怎么利用Golang泛型提高编码效率
    本文小编为大家详细介绍“怎么利用Golang泛型提高编码效率”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么利用Golang泛型提高编码效率”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。工具函数虽然标准库里面...
    99+
    2023-07-05
  • Golang 泛型功能探索:提升编程效率的利器
    随着软件开发领域的不断发展,编程语言的功能也在不断完善和更新。其中,Golang 作为一门吸引众多开发者的编程语言,其简洁、高效的特点备受推崇。然而,长期以来 Golang 在泛型方面...
    99+
    2024-03-05
    功能 golang 泛型
  • C#高级静态语言效率利器之泛型详解
    目录引入类型约束子类泛型常用的泛型数据结构泛型委托引入 所谓泛型,就是创建一个函数,对所有数据类型都生效。最常见的例子就是运算符,毕竟1+1=2,1.0+1.0=2.0,足以看出+是...
    99+
    2023-02-27
    C#泛型使用 C#泛型
  • C#开发中如何使用集合和泛型提高代码效率
    C#开发中如何使用集合和泛型提高代码效率在C#开发中,集合(Collection)和泛型(Generic)是提高代码效率的重要工具。集合提供了一组通用的数据结构和算法,而泛型则允许我们在编写代码时使用一种更加通用和类型安全的方式来操作数据。...
    99+
    2023-10-22
    效率 集合 泛型
  • 如何使用泛型编写高性能的golang代码
    泛型在 go 语言中引入灵活性、复用性并提升性能,通过使用类型约束确保类型参数具有所需的行为。泛型函数、类型和数据结构的实战案例包括缓存数据结构和基准测试,这可以显著提高代码性能,从而优...
    99+
    2024-05-03
    golang 泛型
  • javaweb开发提高效率利器JRebel详解
    JRebel用了有一段时间了,发现确实好用,节省了很多不必要的时间,提高了开发效率。在这里记录一下他的安装和使用过程,希望能帮助到有需要的人。 官网:https://www.jreb...
    99+
    2024-04-02
  • 如何利用数组提高Java对象编程的效率?
    在Java编程中,对象是非常重要的概念。然而,当处理大量对象时,会导致程序变慢并且占用大量内存。为了解决这些问题,可以使用数组来提高Java对象编程的效率。 数组是一种存储多个相同类型元素的数据结构。在Java中,可以使用数组来存储对象,...
    99+
    2023-10-31
    对象 编程算法 数组
  • ASP编程中如何利用索引提高查询效率?
    在ASP编程中,查询数据库是非常常见的操作。但是,如果数据量过大,查询效率就会变得很低,影响用户体验。为了提高查询效率,我们可以使用索引来优化查询操作。 一、什么是索引? 索引是一种数据结构,它可以帮助我们快速定位数据库中的数据。在数据库...
    99+
    2023-07-02
    编程算法 索引 numy
  • PHP、Git和IDE:如何利用这三种工具来提高编码效率?
    在软件开发领域,提高编码效率是开发者们一直致力于解决的问题。而PHP、Git和IDE是三种非常重要的工具,它们可以帮助开发者们提高编码效率。在本文中,我们将讨论如何使用这三种工具来提高编码效率。 一、PHP PHP是一种广泛应用的服务器端...
    99+
    2023-09-11
    git ide 关键字
  • 如何在Go中使用IDE来提高编码效率?
    在Go语言中使用IDE可以帮助开发人员提高编码效率。本文将介绍如何使用一些流行的IDE来提高在Go语言中的编码效率。我们将会涉及到以下IDE:Visual Studio Code、GoLand和LiteIDE。 Visual Studio...
    99+
    2023-06-24
    存储 ide laravel
  • Golang开发工具推荐:提高编程效率的利器
    在当前快节奏和高竞争的软件开发行业中,提高编码效率和开发质量是每个开发者都追求的目标。为了帮助开发者更高效地进行软件开发,Golang(Go语言)成为了一种备受推崇的编程语言。Golang的简洁性、高效性和并...
    99+
    2024-01-20
  • 如何利用ASP编程提高实时JavaScript算法的效率?
    JavaScript是一种广泛使用的编程语言,尤其是在Web应用程序中。然而,JavaScript在处理大量数据或复杂算法时可能会变得很慢,这会影响应用程序的性能和用户体验。在这种情况下,ASP编程可以提高JavaScript算法的效率,...
    99+
    2023-08-15
    编程算法 实时 javascript
  • 提高代码效率的方法:使用Golang
    在当今快节奏的软件开发领域,程序员们不仅需要编写出高效且可靠的代码,还需要不断寻求提升代码效率的方法。而Golang(Go语言)作为一种快速、高效、并发性强的编程语言,正逐渐成为许多开...
    99+
    2024-02-25
    性能优化 并发编程 简洁语法 go语言 标准库
  • 如何利用Spring框架提高Java编程算法的效率?
    Spring框架是一个流行的Java开发框架,它提供了许多功能强大的工具和组件,用于简化Java应用程序的开发。除了提供基本的应用程序开发支持外,Spring框架还提供了许多其他功能,例如AOP、事务管理、数据访问、Web开发和安全性等。在...
    99+
    2023-09-06
    bash 编程算法 spring
  • 如何利用 Python 编程算法实时接口提高效率?
    Python 是一种非常流行的编程语言,因为它的易学性和灵活性。Python 可以用于许多不同的任务,包括数据科学、机器学习、Web 开发和自动化。在本文中,我们将讨论如何使用 Python 编程算法实时接口提高效率。 什么是实时接口? 实...
    99+
    2023-10-02
    编程算法 接口 实时
  • 了解ASP异步编程和JavaScript数据类型,如何提高代码效率?
    ASP异步编程和JavaScript数据类型是Web开发中非常重要的两个概念。了解它们对于提高代码效率是非常有帮助的。在本文中,我们将介绍ASP异步编程和JavaScript数据类型,并通过演示代码来说明如何使用它们来提高代码效率。 ASP...
    99+
    2023-11-02
    异步编程 javascript 数据类型
  • ASP 日志同步:如何利用编程算法提高效率?
    ASP日志同步:如何利用编程算法提高效率? 在Web应用程序开发中,日志记录是非常重要的一部分,因为它可以帮助开发人员跟踪应用程序中的错误和异常。ASP.NET提供了一个非常好的日志记录机制,可以轻松地记录应用程序中的事件和错误。但是,在多...
    99+
    2023-08-17
    日志 同步 编程算法
  • ASP IDE并发文件:如何提高编码效率?
    在现代软件开发中,IDE(集成开发环境)已经成为了一个必要的工具。它可以帮助开发人员更高效地编写代码、管理项目和调试应用程序。在ASP.NET开发中,Visual Studio是最常用的IDE之一。但是,在多人协作或并发开发的情况下,AS...
    99+
    2023-06-18
    ide 并发 文件
  • python 详解如何使用GPU大幅提高效率
    cupy我觉得可以理解为cuda for numpy,安装方式pip install cupy,假设 import numpy as np import cupy as cp ...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作