当前位置: 首页 > news >正文

golang泛型

泛型

go1.18版本开始支持
在函数上使用[T 支持的类型] 表示泛型,比如

func AddSum[T int|float64](params ...T)(sum T){
  // 一些操作
  return sum
}

自带泛型:

  1. any 表示任何类型,即interface
  2. comparable 表示可以被比较的类型
    comparable is an interface that is implemented by all comparable types
    (booleans, numbers, strings, pointers, channels, arrays of comparable types,
    structs whose fields are all comparable types).
    The comparable interface may only be used as a type parameter constraint,
    not as the type of a variable.

就个人而言,泛型的使用倒是可以解决不同类型的相同函数的编写,但是对于其其它妙用还不太明确,需要慢慢体会

在函数上申明多个类型约束

// 1. 泛型的类型限制,在函数上直接申明该函数支持的多个类型
func AddElem[T int | string](params []T) (sum T) {
    for _, elem := range params {
        sum += elem
    }
    return
}

func TestGenerics_AddElem(t *testing.T) {

    // 1. 在函数上声明泛型支持的多个类型
    // 1.1 传入支持的int
    intSum := AddElem([]int{1, 2, 3, 4, 5, 6, 7, 8, 9})
    t.Logf("测试1.1: 类型=%T,val=%+v", intSum, intSum)

    // 1.2 传入支持的string
    strSum := AddElem([]string{"静", "以", "修", "身", ",", "俭", "以", "养", "德"})
    t.Logf("测试1.2: 类型=%T,val=%+v", strSum, strSum)

    // 1.3 传入不支持的类型  ./generics_test.go:29:24: float64 does not implement int|string
    //floatSum := AddElem([]float64{1, 2, 3, 4, 5, 6, 7, 8, 9})
    //t.Logf("测试1.3: 类型=%T,val=%+v", floatSum, floatSum)
}

声明一个约束集合

// 2 泛型的类型限制,声明一个interface,包括所有需要支持的类型
// ~int 表示底层数据是int
type NumStr interface {
    ~int | ~uint | ~float64 | ~string
}

type MyInt int

func AddNumStr[T NumStr](params []T) (sum T) {
    for _, param := range params {
        sum += param
    }
    return
}

func TestGenerics_AddNumStr(t *testing.T) {
    // 2.1 支持的int
    intSum := AddNumStr([]int{1, 2, 3, 4, 5, 6, 7, 8, 9})
    t.Logf("测试2.1: 类型=%T,val=%+v", intSum, intSum)

    // 2.2 传入支持的string
    strSum := AddNumStr([]string{"风", "平", "浪", "静"})
    t.Logf("测试2.2: 类型=%T,val=%+v", strSum, strSum)

    // 2.3 传入自定义int
    myIntSum := AddNumStr([]MyInt{1, 2, 3, 4, 5, 6, 7, 8, 9})
    t.Logf("测试2.3: 类型=%T,val=%+v", myIntSum, myIntSum)
}

泛型切片

// 3. 泛型切片
// any为泛型自带的一种类型,即interface
type Vector[T any] []T
type NumSlice[T int | float64] []T

func AddElem[T int | string](params []T) (sum T) {
    for _, elem := range params {
        sum += elem
    }
    return
}

func TestGenerics_Slice(t *testing.T) {
    // 测试3.1
    v := Vector[string]{"z", "x", "c"}
    t.Logf("测试3.1: 类型=%T,val=%+v", v, v)

    // 测试3.2
    ns := NumSlice[int]{1, 2, 3, 4, 5, 6}
    t.Logf("测试3.2: 类型=%T,val=%+v", ns, ns)

    // 测试3.3
    sum := AddElem(ns)
    t.Logf("测试3.3: 类型=%T,val=%+v", sum, sum)
}

泛型Map

// 4. 泛型map
type M[K string, V any] map[K]V

func TestGenerics_Map(t *testing.T) {
    m := M[string, int]{
        "zx": 123,
        "as": 456,
        "qw": 789,
    }
    t.Logf("测试4.1: 类型=%T,val=%+v", m, m)
}

泛型通道

// 5. 泛型通道
type Ch[T any] chan T

func TestGenerics_Chan(t *testing.T) {
    ch := make(Ch[int], 1)
    ch <- 10

    res := <-ch
    t.Logf("测试5.1: 类型=%T,val=%+v", res, res)
    t.Logf("测试5.2: 类型=%T,val=%+v", ch, ch)
}

方法约束

// 6. 方法约束
type FlyAnimal interface {
    ToString() string
}

// Dragon实现了FlyAnimal
type Dragon int

func (d Dragon) ToString() string {
    return "string_" + strconv.Itoa(int(d))
}

// Tiger没有实现flyAnimal
type Tiger int

func PrintStr[T FlyAnimal](params ...T) {
    for _, param := range params {
        fmt.Println(param.ToString())
    }
}

func TestGenerics_Method_limit(t *testing.T) {
    // 测试6.1 传入实现了方法的类型
    dragon := Dragon(1)
    PrintStr(dragon)

    // 测试6.2 传入未实现对应方法的类型  ./generics_test.go:136:13: Tiger does not implement FlyAnimal (missing ToString method)
    //tiger := Tiger(100)
    //PrintStr(tiger)
}

类型加方法的双重约束

// 7. 类型+方法的约束
type CanSpeak interface {
    ~int | ~int32 | ~int64 | ~float32 | ~float64
    Speak() string
}

type Mouth int32

func (m Mouth) Speak() string {
    return fmt.Sprintf("speak %v", m)
}

type Nose string

func (n Nose) Speak() string {
    return fmt.Sprintf("speak %v", n)
}

type Ear int

func SpeakLoudly[T CanSpeak](params []T) {
    for _, param := range params {
        fmt.Println(param.Speak())
    }
}

func TestGenerics_Type_Method_Limit(t *testing.T) {
    // 7.1 测试类型与方法均符合
    SpeakLoudly([]Mouth{1, 2, 3, 4, 5, 6})

    // 7.2 测试类型符合   ./generics_test.go:172:16: Nose does not implement CanSpeak
    //SpeakLoudly([]Nose{"z", "x", "c"})

    // 7.3 测试方法符合   ./generics_test.go:175:16: Ear does not implement CanSpeak (missing Speak method)
    //SpeakLoudly([]Ear{1, 2, 3, 4, 5, 6})
}

参考

golang泛型介绍

最后

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

小编已加密:aHR0cHM6Ly9kb2NzLnFxLmNvbS9kb2MvRFVrVm9aSGxQZUVsTlkwUnc==出于安全原因,我们把网站通过base64编码了,大家可以通过base64解码把网址获取下来。

相关文章:

  • 如何快速安装JDK 1.8 以及配置环境变量
  • DataGrip 如何导出和恢复整个数据库数据,使用单个 SQL 文件
  • 基于SpringBoot+MyBatisPlus+DynamicDatasource+mysql的多数据源本地事务方案
  • 计算机毕业设计ssm+vue基本微信的健康食谱交流 论坛小程序
  • 天龙八部科举答题问题和答案(全5/8)
  • Python Matplotlib库:基本绘图补充
  • 类与对象(下)
  • 【DouZero】 强化学习+self play达到人类玩家斗地主水平。
  • CMake Tutorial 巡礼(5)_添加系统自察
  • 注意力机制(attention)学习笔记
  • Cocos3.x 对象池NodePool使用介绍和注意事项
  • 计算机二级WPS 选择题(模拟和解析二)
  • java计算机毕业设计基于安卓Android微信的儿童疫苗接种管理小程序uniApp
  • 什么是协程?
  • [配置] 安卓 | 将微信公众号文章保存到Notion
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • C++类的相互关联
  • js写一个简单的选项卡
  • mysql innodb 索引使用指南
  • SwizzleMethod 黑魔法
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • XML已死 ?
  • 当SetTimeout遇到了字符串
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 分布式任务队列Celery
  • 排序算法之--选择排序
  • 普通函数和构造函数的区别
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 协程
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • k8s使用glusterfs实现动态持久化存储
  • ​插件化DPI在商用WIFI中的价值
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • (003)SlickEdit Unity的补全
  • (52)只出现一次的数字III
  • (附源码)springboot优课在线教学系统 毕业设计 081251
  • (附源码)ssm智慧社区管理系统 毕业设计 101635
  • (附源码)计算机毕业设计SSM疫情下的学生出入管理系统
  • (机器学习-深度学习快速入门)第三章机器学习-第二节:机器学习模型之线性回归
  • (十五)使用Nexus创建Maven私服
  • (四)Controller接口控制器详解(三)
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)iOS字体
  • .halo勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET CF命令行调试器MDbg入门(一)
  • .net 按比例显示图片的缩略图
  • .net访问oracle数据库性能问题
  • .NET企业级应用架构设计系列之结尾篇
  • .net通用权限框架B/S (三)--MODEL层(2)
  • :=
  • [ 渗透工具篇 ] 一篇文章让你掌握神奇的shuize -- 信息收集自动化工具
  • [AutoSar NVM] 存储架构
  • [AX]AX2012开发新特性-禁止表或者表字段