设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间00 现在时间00 缓存数据 对自己狠一点,逼自己努力,再过几年你将会感谢今天发狠的自己、恨透今天懒惰自卑的自己。晚安!

对自己狠一点,逼自己努力,再过几年你将会感谢今天发狠的自己、恨透今天懒惰自卑的自己。晚安!

查看: 1021|回复: 3

Go语言利用泛型封装常见的Map操作

[复制链接]

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
24
主题
22
精华
0
金钱
78
积分
46
注册时间
2023-9-29
最后登录
2025-8-31

发表于 2025-2-8 20:37:01 | 显示全部楼层 |阅读模式
目录


  • 什么是泛型
  • 泛型解决了什么问题
  • Go泛型
  • 基于泛型的常见Map操作
  • 代码合集
  • 总结

什么是泛型

泛型是一种编程范式,允许开发者在编写代码时定义通用的类型参数,而不是具体的类型。通过泛型,可以编写出能够处理多种数据类型的代码,而无需为每种类型重复编写相同的逻辑。例如,一个泛型函数可以同时处理整数、浮点数、字符串等多种类型的数据。

泛型解决了什么问题

在 Go 语言引入泛型之前,开发者在处理不同数据类型时,往往需要编写重复的代码。例如,实现一个排序算法,可能需要为整数、浮点数、字符串等分别编写不同的版本。这种重复不仅增加了代码量,也降低了代码的可维护性。引入泛型后,可以通过定义一个通用的类型参数,编写一个通用的排序函数,从而提高代码的复用性和可维护性。

Go泛型

Go 语言在 1.18 版本中引入了泛型,这是 Go 语言发展的一个重要里程碑,它极大地增强了语言的表达能力和灵活性。

基于泛型的常见Map操作

在上一篇文章里,我们使用Go泛型打造了一个优雅的切片工具库,本篇博客将利用Go泛型,封装常见的Map操作,并配套相应的单元测试。本篇博客所编写的代码,皆可直接集成到生产环境的公共代码库中。各位小伙伴可以根据自身项目的实际情况,将对你们项目有帮助的代码迁移到自己的项目当中。
1.获取map的所有keys
  1. func GetMapKeys[K comparable, V any](m map[K]V) []K {
  2.     keys := make([]K, 0, len(m))
  3.     for k := range m {
  4.        keys = append(keys, k)
  5.     }
  6.     return keys
  7. }
复制代码
2.根据过滤条件获取map的keys
  1. func GetMapKeysMatchCondition[K comparable, V any](m map[K]V, condition func(K, V) bool) []K {
  2.     keys := make([]K, 0, len(m))
  3.     for k, v := range m {
  4.        if condition(k, v) {
  5.           keys = append(keys, k)
  6.        }
  7.     }
  8.     return keys
  9. }
复制代码
3.获取map的所有values
  1. func GetMapValues[K comparable, V any](m map[K]V) []V {
  2.     values := make([]V, 0, len(m))
  3.     for _, v := range m {
  4.        values = append(values, v)
  5.     }
  6.     return values
  7. }
复制代码
4.根据过滤条件获取map的values
  1. func GetMapValuesMatchCondition[K comparable, V any](m map[K]V, condition func(K, V) bool) []V {
  2.     values := make([]V, 0, len(m))
  3.     for k, v := range m {
  4.        if condition(k, v) {
  5.           values = append(values, v)
  6.        }
  7.     }
  8.     return values
  9. }
复制代码
5.合并多个map
  1. func MergeMaps[K comparable, V any](maps ...map[K]V) map[K]V {
  2.     mergeMap := make(map[K]V)
  3.     for _, m := range maps {
  4.        for k, v := range m {
  5.           mergeMap[k] = v
  6.        }
  7.     }
  8.     return mergeMap
  9. }
复制代码
6.map转切片
  1. func MapToSlice[K comparable, V any, T any](m map[K]V, extractor func(V) T) []T {
  2.     res := make([]T, 0, len(m))
  3.     for _, v := range m {
  4.        res = append(res, extractor(v))
  5.     }
  6.     return res
  7. }
复制代码
7.切片转map
  1. func SliceToMap[T any, K comparable](s []T, keyFunc func(T) K) map[K]T {
  2.     res := make(map[K]T)
  3.     for _, v := range s {
  4.        key := keyFunc(v)
  5.        res[key] = v
  6.     }
  7.     return res
  8. }
复制代码
8.复制map
  1. func CopyMap[K comparable, V any](oldMap map[K]V) map[K]V {
  2.     newMap := make(map[K]V, len(oldMap))
  3.     for k, v := range oldMap {
  4.        newMap[k] = v
  5.     }
  6.     return newMap
  7. }
复制代码
9.sync.Map转map
  1. func SyncMapToMap[K comparable, V any](syncMap sync.Map) map[K]V {
  2.     m := make(map[K]V)
  3.     syncMap.Range(func(key, value any) bool {
  4.        // 尝试将key和value转换为指定的类型
  5.        k, ok1 := key.(K)
  6.        v, ok2 := value.(V)
  7.        if ok1 && ok2 {
  8.           m[k] = v
  9.        }
  10.        return true
  11.     })
  12.     return m
  13. }
复制代码
10.map转sync.Map
  1. func MapToSyncMap[K comparable, V any](m map[K]V) *sync.Map {
  2.     syncMap := &sync.Map{}
  3.     if m == nil {
  4.        return syncMap
  5.     }
  6.     for k, v := range m {
  7.        syncMap.Store(k, v)
  8.     }
  9.     return syncMap
  10. }
复制代码
代码合集

我将上述所有代码集成到一个maps.go文件当中,并配套了单元测试文件maps_test.go。如果各位小伙伴们的项目有需要,只需将以下代码完整拷贝到你们项目的基础代码工具库即可。
maps.go
  1. package mapsimport (    "sync")// 获取map的所有keysfunc GetMapKeys[K comparable, V any](m map[K]V) []K {
  2.     keys := make([]K, 0, len(m))
  3.     for k := range m {
  4.        keys = append(keys, k)
  5.     }
  6.     return keys
  7. }// 根据过滤条件获取map的keysfunc GetMapKeysMatchCondition[K comparable, V any](m map[K]V, condition func(K, V) bool) []K {
  8.     keys := make([]K, 0, len(m))
  9.     for k, v := range m {
  10.        if condition(k, v) {
  11.           keys = append(keys, k)
  12.        }
  13.     }
  14.     return keys
  15. }func GetMapValues[K comparable, V any](m map[K]V) []V {
  16.     values := make([]V, 0, len(m))
  17.     for _, v := range m {
  18.        values = append(values, v)
  19.     }
  20.     return values
  21. }// 根据过滤条件获取map的valuesfunc GetMapValuesMatchCondition[K comparable, V any](m map[K]V, condition func(K, V) bool) []V {
  22.     values := make([]V, 0, len(m))
  23.     for k, v := range m {
  24.        if condition(k, v) {
  25.           values = append(values, v)
  26.        }
  27.     }
  28.     return values
  29. }// 合并多个mapfunc MergeMaps[K comparable, V any](maps ...map[K]V) map[K]V {
  30.     mergeMap := make(map[K]V)
  31.     for _, m := range maps {
  32.        for k, v := range m {
  33.           mergeMap[k] = v
  34.        }
  35.     }
  36.     return mergeMap
  37. }// map转切片func MapToSlice[K comparable, V any, T any](m map[K]V, extractor func(V) T) []T {
  38.     res := make([]T, 0, len(m))
  39.     for _, v := range m {
  40.        res = append(res, extractor(v))
  41.     }
  42.     return res
  43. }// 切片转mapfunc SliceToMap[T any, K comparable](s []T, keyFunc func(T) K) map[K]T {
  44.     res := make(map[K]T)
  45.     for _, v := range s {
  46.        key := keyFunc(v)
  47.        res[key] = v
  48.     }
  49.     return res
  50. }// 复制mapfunc CopyMap[K comparable, V any](oldMap map[K]V) map[K]V {
  51.     newMap := make(map[K]V, len(oldMap))
  52.     for k, v := range oldMap {
  53.        newMap[k] = v
  54.     }
  55.     return newMap
  56. }// sync.Map转mapfunc SyncMapToMap[K comparable, V any](syncMap sync.Map) map[K]V {
  57.     m := make(map[K]V)
  58.     syncMap.Range(func(key, value any) bool {
  59.        // 尝试将key和value转换为指定的类型
  60.        k, ok1 := key.(K)
  61.        v, ok2 := value.(V)
  62.        if ok1 && ok2 {
  63.           m[k] = v
  64.        }
  65.        return true
  66.     })
  67.     return m
  68. }func MapToSyncMap[K comparable, V any](m map[K]V) *sync.Map {
  69.     syncMap := &sync.Map{}
  70.     if m == nil {
  71.        return syncMap
  72.     }
  73.     for k, v := range m {
  74.        syncMap.Store(k, v)
  75.     }
  76.     return syncMap
  77. }
复制代码
maps_test.go
  1. package maps

  2. import (
  3.     "sync"
  4.     "testing"
  5. )

  6. // 测试 GetMapKeys 函数
  7. func TestGetMapKeys(t *testing.T) {
  8.     m := map[string]int{
  9.        "apple":  1,
  10.        "banana": 2,
  11.        "cherry": 3,
  12.     }
  13.     keys := GetMapKeys(m)
  14.     if len(keys) != len(m) {
  15.        t.Errorf("Expected %d keys, got %d", len(m), len(keys))
  16.     }
  17.     for _, k := range keys {
  18.        if _, exists := m[k]; !exists {
  19.           t.Errorf("Key %s not found in original map", k)
  20.        }
  21.     }
  22. }

  23. // 测试 GetMapKeysMatchCondition 函数
  24. func TestGetMapKeysMatchCondition(t *testing.T) {
  25.     m := map[string]int{
  26.        "apple":  1,
  27.        "banana": 2,
  28.        "cherry": 3,
  29.     }
  30.     condition := func(k string, v int) bool {
  31.        return v > 1
  32.     }
  33.     keys := GetMapKeysMatchCondition(m, condition)
  34.     for _, k := range keys {
  35.        if m[k] <= 1 {
  36.           t.Errorf("Key %s should not be included as its value is not greater than 1", k)
  37.        }
  38.     }
  39. }

  40. // 测试 GetMapValues 函数
  41. func TestGetMapValues(t *testing.T) {
  42.     m := map[string]int{
  43.        "apple":  1,
  44.        "banana": 2,
  45.        "cherry": 3,
  46.     }
  47.     values := GetMapValues(m)
  48.     if len(values) != len(m) {
  49.        t.Errorf("Expected %d values, got %d", len(m), len(values))
  50.     }
  51.     valueSet := make(map[int]bool)
  52.     for _, v := range values {
  53.        valueSet[v] = true
  54.     }
  55.     for _, v := range m {
  56.        if !valueSet[v] {
  57.           t.Errorf("Value %d not found in result values", v)
  58.        }
  59.     }
  60. }

  61. // 测试 GetMapValuesMatchCondition 函数
  62. func TestGetMapValuesMatchCondition(t *testing.T) {
  63.     m := map[string]int{
  64.        "apple":  1,
  65.        "banana": 2,
  66.        "cherry": 3,
  67.     }
  68.     condition := func(k string, v int) bool {
  69.        return v > 1
  70.     }
  71.     values := GetMapValuesMatchCondition(m, condition)
  72.     for _, v := range values {
  73.        if v <= 1 {
  74.           t.Errorf("Value %d should not be included as it is not greater than 1", v)
  75.        }
  76.     }
  77. }

  78. // 测试 MergeMaps 函数
  79. func TestMergeMaps(t *testing.T) {
  80.     m1 := map[string]int{
  81.        "apple":  1,
  82.        "banana": 2,
  83.     }
  84.     m2 := map[string]int{
  85.        "banana": 3,
  86.        "cherry": 4,
  87.     }
  88.     merged := MergeMaps(m1, m2)
  89.     for k := range m1 {
  90.        if _, exists := merged[k]; !exists {
  91.           t.Errorf("key %s not exist in m1", k)
  92.        }
  93.     }
  94.     for k := range m2 {
  95.        if _, exists := merged[k]; !exists {
  96.           t.Errorf("key %s not exist in m2", k)
  97.        }
  98.     }
  99. }

  100. // 测试 MapToSlice 函数
  101. func TestMapToSlice(t *testing.T) {
  102.     m := map[string]int{
  103.        "apple":  1,
  104.        "banana": 2,
  105.        "cherry": 3,
  106.     }
  107.     extractor := func(v int) int {
  108.        return v * 2
  109.     }
  110.     slice := MapToSlice(m, extractor)
  111.     if len(slice) != len(m) {
  112.        t.Errorf("Expected %d elements in slice, got %d", len(m), len(slice))
  113.     }
  114.     for _, v := range m {
  115.        found := false
  116.        for _, s := range slice {
  117.           if s == v*2 {
  118.              found = true
  119.              break
  120.           }
  121.        }
  122.        if !found {
  123.           t.Errorf("Transformed value %d not found in slice", v*2)
  124.        }
  125.     }
  126. }

  127. // 测试 SliceToMap 函数
  128. func TestSliceToMap(t *testing.T) {
  129.     s := []int{1, 2, 3}
  130.     keyFunc := func(v int) int {
  131.        return v * 10
  132.     }
  133.     m := SliceToMap(s, keyFunc)
  134.     if len(m) != len(s) {
  135.        t.Errorf("Expected %d keys in map, got %d", len(s), len(m))
  136.     }
  137.     for _, v := range s {
  138.        key := keyFunc(v)
  139.        if val, exists := m[key]; !exists || val != v {
  140.           t.Errorf("Value for key %d in map does not match original slice", key)
  141.        }
  142.     }
  143. }

  144. // 测试 CopyMap 函数
  145. func TestCopyMap(t *testing.T) {
  146.     oldMap := map[string]int{
  147.        "apple":  1,
  148.        "banana": 2,
  149.        "cherry": 3,
  150.     }
  151.     newMap := CopyMap(oldMap)
  152.     if len(newMap) != len(oldMap) {
  153.        t.Errorf("Expected %d keys in new map, got %d", len(oldMap), len(newMap))
  154.     }
  155.     for k, v := range oldMap {
  156.        if val, exists := newMap[k]; !exists || val != v {
  157.           t.Errorf("Value for key %s in new map does not match original map", k)
  158.        }
  159.     }
  160. }

  161. // 测试 SyncMapToMap 函数
  162. func TestSyncMapToMap(t *testing.T) {
  163.     var syncMap sync.Map
  164.     syncMap.Store("apple", 1)
  165.     syncMap.Store("banana", 2)
  166.     syncMap.Store("cherry", 3)
  167.     m := SyncMapToMap[string, int](syncMap)
  168.     syncMap.Range(func(key, value any) bool {
  169.        k := key.(string)
  170.        v := value.(int)
  171.        if val, exists := m[k]; !exists || val != v {
  172.           t.Errorf("Value for key %s in map does not match sync.Map", k)
  173.        }
  174.        return true
  175.     })
  176. }

  177. // 测试 MapToSyncMap 函数
  178. func TestMapToSyncMap(t *testing.T) {
  179.     m := map[string]int{
  180.        "apple":  1,
  181.        "banana": 2,
  182.        "cherry": 3,
  183.     }
  184.     syncMap := MapToSyncMap(m)
  185.     for k, v := range m {
  186.        value, exists := syncMap.Load(k)
  187.        if !exists || value.(int) != v {
  188.           t.Errorf("Value for key %s in sync.Map does not match original map", k)
  189.        }
  190.     }
  191. }
复制代码
总结

本文使用Go泛型,对常见的Map操作进行了封装,整理出了一个Map工具库maps.go
以上就是Go语言利用泛型封装常见的Map操作的详细内容,更多关于Go泛型封装Map操作的资料请关注晓枫资讯其它相关文章!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
16
积分
12
注册时间
2022-12-24
最后登录
2022-12-24

发表于 2025-3-6 14:29:38 | 显示全部楼层
顶顶更健康!!!
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
16
积分
12
注册时间
2022-12-27
最后登录
2022-12-27

发表于 2025-3-22 08:21:28 | 显示全部楼层
感谢楼主,顶。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
21
积分
22
注册时间
2022-12-25
最后登录
2022-12-25

发表于 2025-12-6 08:54:57 | 显示全部楼层
感谢楼主分享。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼
3楼
4楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表