当前位置:首页 > 文章列表 > Golang > Go教程 > Go 的泛型:编写适用于多种类型的更智能的代码

Go 的泛型:编写适用于多种类型的更智能的代码

来源:dev.to 2024-12-22 16:52:10 0浏览 收藏

珍惜时间,勤奋学习!今天给大家带来《Go 的泛型:编写适用于多种类型的更智能的代码》,正文内容主要涉及到等等,如果你正在学习Golang,或者是对Golang有疑问,欢迎大家关注我!后面我会持续更新相关内容的,希望都能帮到正在学习的大家!

Go 的泛型:编写适用于多种类型的更智能的代码

泛型即将进入 go,这是一件大事。我一直在深入研究 go 2 的拟议更改,并且很高兴分享我对这一强大新功能的了解。

从本质上讲,泛型允许我们编写适用于多种类型的代码。我们可以编写一个通用函数来处理所有这些类型,而不是为整数、字符串和自定义类型编写单独的函数。这会带来更灵活和可重用的代码。

让我们从一个基本示例开始。以下是我们编写通用“max”函数的方法:

func max[t constraints.ordered](a, b t) t {
    if a > b {
        return a
    }
    return b
}

此函数适用于任何满足 ordered 约束的类型 t。我们可以将它与整数、浮点数、字符串或任何实现比较运算符的自定义类型一起使用。

类型约束是 go 泛型实现的关键部分。它们允许我们指定泛型类型必须支持哪些操作。约束包提供了几个预定义的约束,但我们也可以创建自己的约束。

例如,我们可以为可以转换为字符串的类型定义一个约束:

type stringer interface {
    string() string
}

现在我们可以编写适用于任何可以转换为字符串的类型的函数:

func printanything[t stringer](value t) {
    fmt.println(value.string())
}

go 泛型最酷的事情之一就是类型推断。很多情况下,我们在调用泛型函数时不需要显式指定类型参数。编译器可以计算出来:

result := max(5, 10) // type inferred as int

这使我们的代码保持干净和可读,同时仍然提供泛型的好处。

让我们进入一些更高级的领域。类型参数列表允许我们指定多个类型参数之间的关系。以下是在两种类型之间进行转换的函数示例:

func convert[from, to any](value from, converter func(from) to) to {
    return converter(value)
}

这个函数接受任何类型的值,一个转换器函数,并返回转换后的值。它非常灵活,可以在许多不同的场景中使用。

泛型在数据结构方面确实很出色。让我们实现一个简单的通用堆栈:

type stack[t any] struct {
    items []t
}

func (s *stack[t]) push(item t) {
    s.items = append(s.items, item)
}

func (s *stack[t]) pop() (t, bool) {
    if len(s.items) == 0 {
        var zero t
        return zero, false
    }
    item := s.items[len(s.items)-1]
    s.items = s.items[:len(s.items)-1]
    return item, true
}

这个堆栈可以容纳任何类型的物品。我们可以使用相同的代码创建整数、字符串或自定义结构的堆栈。

泛型还为 go 中的设计模式开辟了新的可能性。例如,我们可以实现一个通用的观察者模式:

type observable[t any] struct {
    observers []func(t)
}

func (o *observable[t]) subscribe(f func(t)) {
    o.observers = append(o.observers, f)
}

func (o *observable[t]) notify(data t) {
    for _, f := range o.observers {
        f(data)
    }
}

这使我们能够为任何类型的数据创建可观察的对象,从而轻松实现事件驱动的架构。

在重构现有 go 代码以使用泛型时,保持平衡很重要。虽然泛型可以使我们的代码更加灵活和可重用,但它们也可以使其变得更加复杂和难以理解。我发现通常最好从具体实现开始,只有当我们看到清晰的重复模式时才引入泛型。

例如,如果我们发现自己为不同类型编写类似的函数,那么这是泛化的一个很好的候选者。但如果一个函数仅用于一种类型,最好保持原样。

泛型真正发挥作用的一个领域是实现算法。让我们看一下通用的快速排序实现:

func quicksort[t constraints.ordered](slice []t) {
    if len(slice) < 2 {
        return
    }
    pivot := slice[0]
    left, right := 1, len(slice)-1
    for left <= right {
        if slice[left] <= pivot {
            left++
        } else if slice[right] > pivot {
            right--
        } else {
            slice[left], slice[right] = slice[right], slice[left]
        }
    }
    slice[0], slice[right] = slice[right], slice[0]
    quicksort(slice[:right])
    quicksort(slice[right+1:])
}

该函数可以对任何有序类型的切片进行排序。我们可以使用它对整数、浮点数、字符串或任何实现比较运算符的自定义类型进行排序。

在大型项目中使用泛型时,考虑灵活性和编译时类型检查之间的权衡至关重要。虽然泛型允许我们编写更灵活的代码,但如果我们不小心,它们也可能更容易引入运行时错误。

我发现有用的一个策略是对内部库代码使用泛型,但在公共 api 中公开具体类型。这为我们带来了内部代码重用的好处,同时仍然为我们库的用户提供了清晰的、类型安全的界面。

另一个重要的考虑因素是性能。虽然 go 的泛型实现被设计得非常高效,但与具体类型相比,仍然存在一些运行时开销。在性能关键型代码中,可能值得对通用实现与非通用实现进行基准测试,看看是否存在显着差异。

泛型还为 go 中的元编程开辟了新的可能性。我们可以编写对类型本身进行操作的函数,而不是对值进行操作。例如,我们可以编写一个在运行时生成新结构类型的函数:

func MakeStruct[T any](fields ...string) (reflect.Type, error) {
    var structFields []reflect.StructField
    for _, field := range fields {
        structFields = append(structFields, reflect.StructField{
            Name: field,
            Type: reflect.TypeOf((*T)(nil)).Elem(),
        })
    }
    return reflect.StructOf(structFields), nil
}

该函数创建一个新的结构类型,其中字段类型为 t。它是在运行时创建动态数据结构的强大工具。

在我们结束时,值得注意的是,虽然泛型是一个强大的功能,但它们并不总是最好的解决方案。有时,简单的接口或具体的类型更合适。关键是明智地使用泛型,它们在代码重用和类型安全方面提供了明显的好处。

go 2 中的泛型代表了该语言的重大演变。它们提供了新的工具来编写灵活、可重用的代码,同时保持 go 对简单性和可读性的重视。随着我们继续探索和试验此功能,我很高兴看到它将如何塑造 go 编程的未来。


我们的创作

一定要看看我们的创作:

投资者中心 | 智能生活 | 时代与回声 | 令人费解的谜团 | 印度教 | 精英开发 | js学校


我们在媒体上

科技考拉洞察 | 时代与回响世界 | 投资者中央媒体 | 令人费解的谜团 | 科学与时代媒介 | 现代印度教

以上就是《Go 的泛型:编写适用于多种类型的更智能的代码》的详细内容,更多关于的资料请关注golang学习网公众号!

版本声明
本文转载于:dev.to 如有侵犯,请联系study_golang@163.com删除
一汽解放:预计2030年公司全球销量超50万辆,海外占比达36%一汽解放:预计2030年公司全球销量超50万辆,海外占比达36%
上一篇
一汽解放:预计2030年公司全球销量超50万辆,海外占比达36%
Win10玩游戏时怎么禁用输入法
下一篇
Win10玩游戏时怎么禁用输入法
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    508次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    497次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • SEO标题魔匠AI:高质量学术写作平台,毕业论文生成与优化专家
    魔匠AI
    SEO摘要魔匠AI专注于高质量AI学术写作,已稳定运行6年。提供无限改稿、选题优化、大纲生成、多语言支持、真实参考文献、数据图表生成、查重降重等全流程服务,确保论文质量与隐私安全。适用于专科、本科、硕士学生及研究者,满足多语言学术需求。
    20次使用
  • PPTFake答辩PPT生成器:一键生成高效专业的答辩PPT
    PPTFake答辩PPT生成器
    PPTFake答辩PPT生成器,专为答辩准备设计,极致高效生成PPT与自述稿。智能解析内容,提供多样模板,数据可视化,贴心配套服务,灵活自主编辑,降低制作门槛,适用于各类答辩场景。
    36次使用
  • SEO标题Lovart AI:全球首个设计领域AI智能体,实现全链路设计自动化
    Lovart
    SEO摘要探索Lovart AI,这款专注于设计领域的AI智能体,通过多模态模型集成和智能任务拆解,实现全链路设计自动化。无论是品牌全案设计、广告与视频制作,还是文创内容创作,Lovart AI都能满足您的需求,提升设计效率,降低成本。
    49次使用
  • 美图AI抠图:行业领先的智能图像处理技术,3秒出图,精准无误
    美图AI抠图
    美图AI抠图,依托CVPR 2024竞赛亚军技术,提供顶尖的图像处理解决方案。适用于证件照、商品、毛发等多场景,支持批量处理,3秒出图,零PS基础也能轻松操作,满足个人与商业需求。
    46次使用
  • SEO标题PetGPT:智能桌面宠物程序,结合AI对话的个性化陪伴工具
    PetGPT
    SEO摘要PetGPT 是一款基于 Python 和 PyQt 开发的智能桌面宠物程序,集成了 OpenAI 的 GPT 模型,提供上下文感知对话和主动聊天功能。用户可高度自定义宠物的外观和行为,支持插件热更新和二次开发。适用于需要陪伴和效率辅助的办公族、学生及 AI 技术爱好者。
    45次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码