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

2025-02-08 04:50

本文主要是介绍Go语言利用泛型封装常见的Map操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Go语言利用泛型封装常见的Map操作》Go语言在1.18版本中引入了泛型,这是Go语言发展的一个重要里程碑,它极大地增强了语言的表达能力和灵活性,本文将通过泛型实现封装常见的Map操作,感...

什么是泛型

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

泛型解决了什么问题

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

Go泛型

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

基于泛型的常见Map操作

在上一篇文章里,我们使用Go泛型打造了一个优雅的切片工具库,本篇博客将利用Go泛型,封装常见的Map操作,并配套相应的单元测试。本篇博客所编写的代码,皆可直接集成到生产环境的公共代码库中。各位小伙伴可以根据自身项目的实际情况,将对你们项目有帮助的代码迁移到自己的项目当中。

1.获取map的所有keys

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

2.根据过滤条件获取map的keys

func GetMapKeysMatchCondition[K comparable, V any](m map[K]V, condition func(K, V) bool) []K {
    keys := make([]K, 0, len(m))
    for k, v := range m {
       if condition(k, v) {
          keys = append(keys, k)
       }
    }
    return keys
}

3.获取map的所有values

func GetMapValues[K comparable, V any](m map[K]V) []V {
    values := make([]V, 0, len(m))
    for _, v := range m {
       values = append(values, v)
    }
    return values
}

4.根据过滤条件获取map的values

func GetMapValuesMatchCondition[K comparable, V any](m map[K]V, condition func(K, V) bool) []V {
    values := make([]V, 0, len(m))
    for k, v := range m {
       if condition(k, v) {
          values = append(values, v)
       }
    }
    return values
}

5.合并多个map

func MergeMaps[K comparable, V any](maps ...map[K]V) map[K]V {
    mergeMap := make(map[K]V)
    for _, m := range maps {
       for k, v := range m {
          mergeMap[k] = v
       }
    }
    return mergeMap
}

6.map转切片

func MapToSlice[K comparable, V any, T any](m map[K]V, extractor func(V) T) []T {
    res := make([]T, 0, len(m))
    for _, v := range m {
       res = append(res, extractor(v))
    }
    return res
}

7.切片转map

func SliceToMap[T any, K comparable](s []T, keyFunc func(T) K) map[K]T {
    res := make(map[K]T)
    for _, v := range s {
       key := keyFunc(v)
       res[key] = v
    }
    return res
}

8.复制map

func CopyMap[K comparable, V any](oldMap map[K]V) map[K]V {
    newMap := make(map[K]V, len(oldMap))
    for k, v := range oldMap {
       newMap[k] = v
    }
    return newMap
}

9.sync.Map转map

func SyncMapToMap[K comparable, V any](syncMap sync.Map) map[K]V {
    m := make(map[K]V)
    syncMap.Range(func(key, value any) bool {
       // 尝试将key和value转换为指定的类型
       k, ok1 := key.(K)
       v, ok2 := value.(V)
       if ok1 && ok2 {
          m[k] =python v
       }
       return true
    })
    return m
}

10.map转sync.Map

func MapToSyncMap[K comparable, V any](m map[K]V) *sync.Map android{
    syncMap := &sync.Map{}
    if m == nil {
       return syncMap
    }
    for k, v := range m {
       syncMap.Store(k, v)
    }
    return syncMap
}

代码合集

我将上述所有代码集成到一个maps.go文件当中,并配套了单元测试文件maps_test.go。如果各位小伙伴们的项目有需要,只需将以下代码完整拷贝到你们项目的基础代码工具库即可。

maps.go

package maps

import (
    "sync"
)

// 获取map的所有keys
func GetMapKeys[K comparable, V any](m map[K]V) []K {
    keys := make([]K, 0, len(m))
    for k := range m {
       keys = append(keys, k)
    }
    return keys
}

// 根据过滤条件获取map的keys
func GetMapKeysMatchCondition[K comparable, V any](m map[K]V, condition func(K, V) bool) []K {
    keys := make([]K, 0, len(m))
    for k, v := range m {
       if condition(k, v) {
          keys = append(keys, k)
       }
    }
    return keys
}

func GetMapValues[K comparable, V any](m map[K]V) []V {
    values := make([]V, 0, len(m))
    for _, v := range m {
       values = append(values, v)
    }
    return values
}

// 根据过滤条件获取map的values
func GetMapValuesMatchCondition[K comparable, V any](m map[K]V, condition func(K, V) bool) []V {
    values :China编程= make([]V, 0, len(m))
    for k, v := range m {
       if condition(k, v) {
          values = append(values, v)
       }
    }
    return values
}

// 合并多个map
func MergeMaps[K comparable, V any](maps ...map[K]V) map[K]V {
    mergeMap := make(map[K]V)
    for _, m := range maps {
       for k, v := range m {
          mergeMap[k] = v
       }
    }
    return mergeMap
}

// map转切片
func MapToSlice[K comparable, V any, T any](m map[K]V, extractor func(V) T) []T {
    res := make([]T, 0, len(m))
    for _, v := range m {
       res = append(res, extractor(v))
    }
    return res
}

// 切片转map
func SliceToMap[T any, K comparable](s []T, keyFunc func(T) K) map[K]T {
    res := make(map[K]T)
    for _, v := range s {
       key := keyFunc(v)
       res[key] = v
    }
    return res
}

// 复制map
func CopyMap[K comparable, V any](oldMap map[K]V) map[K]V {
    newMap := make(map[K]V, len(oldMap))
    for k, v := range oldMap {
       newMap[k] = v
    }
    return newMap
}

// sync.Map转map
func SyncMapToMap[K comparable, V any](syncMap sync.Map) map[K]V {
    m := make(map[K]V)
    syncMap.Range(func(key, value any) bool {
       // 尝试将key和value转换为指定的类型
       k, ok1 := key.(K)
       v, ok2 := value.(V)
       if ok1 && ok2 {
          m[k] = v
       }
       return true
    })
 python   return m
}

func MapToSyncMap[K comparable, V any](m map[K]V) *sync.Map {
    syncMap := &sync.Map{}
    if m == nil {
       return syncMap
    }
    for k, v := range m {
       syncMap.Store(k, v)
    }
    return syncMap
}

maps_test.go

package maps

import (
    "sync"
    "testing"
)

// 测试 GetMapKeys 函数
func TestGetMapKeys(t *testing.T) {
    m := map[string]int{
       "apple":  1,
       "banana": 2,
       "cherry": 3,
    }
    keys := GetMapKeys(m)
    if len(keys) != len(m) {
       t.Errorf("Expected %d keys, got %d", len(m), len(keys))
    }
    for _, k := range keys {
       if _, exists := m[k]; !exists {
          t.Errorf("Key %s not found in original map", k)
       }
    }
}

// 测试 GetMapKeysMatchCondition 函数
func TestGetMapKeysMatchCondition(t *testing.T) {
    m := map[string]int{
       "apple":  1,
       "banana": 2,
       "cherry": 3,
    }
    condition := func(k string, v int) bool {
       return v > 1
    }
    keys := GetMapKeysMatchCondition(m, condition)
    for _, k := range keys {
       if m[k] <= 1 {
          t.Errorf("Key %s should not be included as its value is not greater than 1", k)
       }
    }
}

// 测试 GetMapValues 函数
func TestGetMapValues(t *testing.T) {
    m := map[string]int{
       "apple":  1,
       "banana": 2,
       "cherry": 3,
    }
    values := GetMapValues(m)
    if len(values) != len(m) {
       t.Errorf("Expected %d values, got %d", len(m), len(values))
    }
    valueSet := make(map[int]bool)
    for _, v := range values {
       valueSet[v] = true
    }
    for _, v := range m {
       if !valueSet[v] {
          t.Errorf("Value %d not found in result values", v)
       }
    }
}

// 测试 GetMapValuesMatchCondition 函数
func TestGetMapValuesMatchCondition(t *testing.T) {
    m := map[string]int{
       "apple":  1,
       "banana": 2,
       "cherry": 3,
    }
    condition := func(k string, v int) bool {
       return v > 1
    }
    values := GetMapValuesMatchCondition(m, condition)
    for _, v := range values {
       if v <= 1 {
          t.Errorf("Value %d should not be included as it is not greater than 1", v)
       }
    }
}

// 测试 MergeMaps 函数
func TestMergeMaps(t *testing.T) {
    m1 := map[string]int{
       "apple":  1,
       "banana": 2,
    }
    m2 := map[string]int{
       "banana": 3,
       "cherry": 4,
    }
    merged := MergeMaps(m1, m2)
    for k := range m1 {
       if _, exists := merged[k]; !exists {
          t.Errorf("key %s not exist in m1", k)
       }
    }
    for k := range m2 {
       if _, exists := merged[k]; !exists {
          t.Errorf("key %s not exist in m2", k)
       }
    }
}

// 测试 MapToSlice 函数
func TestMapToSlice(t *testing.T) {
    m := map[string]int{
       "apple":  1,
       "banana": 2,
       "cherry": 3,
    }
    extractor := func(v int) int {
     js  return v * 2
    }
    slice := MapToSlice(m, extractor)
    if len(slice) != len(m) {
       t.Errorf("Expected %d elements in slice, got %d", len(m), len(slice))
    }
    for _, v := range m {
       found := false
       for _, s := range slice {
          if s == v*2 {
             found = true
             break
          }
       }
       if !found {
          t.Errorf("Transformed value %d not found in slice", v*2)
       }
    }
}

// 测试 SliceToMap 函数
func TestSliceToMap(t *testing.T) {
    s := []int{1, 2, 3}
    keyFunc := func(v int) int {
       return v * 10
    }
    m := SliceToMap(s, keyFunc)
    if len(m) != len(s) {
       t.Errorf("Expected %d keys in map, got %d", len(s), len(m))
    }
    for _, v := range s {
       key := keyFunc(v)
       if val, exists := m[key]; !exists || val != v {
          t.Errorf("Value for key %d in map does not match original slice", key)
       }
    }
}

// 测试 CopyMap 函数
func TestCopyMap(t *testing.T) {
    oldMap := map[string]int{
       "apple":  1,
       "banana": 2,
       "cherry": 3,
    }
    newMap := CopyMap(oldMap)
    if len(newMap) != len(oldMap) {
       t.Errorf("Expected %d keys in new map, got %d", len(oldMap), len(newMap))
    }
    for k, v := range oldMap {
       if val, exists := newMap[k]; !exists || val != v {
          t.Errorf("Value for key %s in new map does not match original map", k)
       }
    }
}

// 测试 SyncMapToMap 函数
func TestSyncMapToMap(t *testing.T) {
    var syncMap sync.Map
    syncMap.Store("apple", 1)
    syncMap.Store("banana", 2)
    syncMap.Store("cherry", 3)
    m := SyncMapToMap[string, int](syncMap)
    syncMap.Range(func(key, value any) bool {
       k := key.(string)
       v := value.(int)
       if val, exists := m[k]; !exists || val != v {
          t.Errorf("Value for key %s in map does not match sync.Map", k)
       }
       return true
    })
}

// 测试 MapToSyncMap 函数
func TestMapToSyncMap(t *testing.T) {
    m := map[string]int{
       "apple":  1,
       "banana": 2,
       "cherry": 3,
    }
    syncMap := MapToSyncMap(m)
    for k, v := range m {
       value, exists := syncMap.Load(k)
       if !exists || value.(int) != v {
          t.Errorf("Value for key %s in sync.Map does not match original map", k)
       }
    }
}

总结

本文使用Go泛型,对常见的Map操作进行了封装,整理出了一个Map工具库maps.go

以上就是Go语言利用泛型封装常见的Map操作的详细内容,更多关于Go泛型封装Map操作的资料请关注China编程(www.chinasem.cn)其它相关文章!

这篇关于Go语言利用泛型封装常见的Map操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153336

相关文章

java中long的一些常见用法

《java中long的一些常见用法》在Java中,long是一种基本数据类型,用于表示长整型数值,接下来通过本文给大家介绍java中long的一些常见用法,感兴趣的朋友一起看看吧... 在Java中,long是一种基本数据类型,用于表示长整型数值。它的取值范围比int更大,从-922337203685477

SQL中JOIN操作的条件使用总结与实践

《SQL中JOIN操作的条件使用总结与实践》在SQL查询中,JOIN操作是多表关联的核心工具,本文将从原理,场景和最佳实践三个方面总结JOIN条件的使用规则,希望可以帮助开发者精准控制查询逻辑... 目录一、ON与WHERE的本质区别二、场景化条件使用规则三、最佳实践建议1.优先使用ON条件2.WHERE用

Java中Map.Entry()含义及方法使用代码

《Java中Map.Entry()含义及方法使用代码》:本文主要介绍Java中Map.Entry()含义及方法使用的相关资料,Map.Entry是Java中Map的静态内部接口,用于表示键值对,其... 目录前言 Map.Entry作用核心方法常见使用场景1. 遍历 Map 的所有键值对2. 直接修改 Ma

Linux链表操作方式

《Linux链表操作方式》:本文主要介绍Linux链表操作方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、链表基础概念与内核链表优势二、内核链表结构与宏解析三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势六、典型应用场景七、调试技巧与

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

Go语言中泄漏缓冲区的问题解决

《Go语言中泄漏缓冲区的问题解决》缓冲区是一种常见的数据结构,常被用于在不同的并发单元之间传递数据,然而,若缓冲区使用不当,就可能引发泄漏缓冲区问题,本文就来介绍一下问题的解决,感兴趣的可以了解一下... 目录引言泄漏缓冲区的基本概念代码示例:泄漏缓冲区的产生项目场景:Web 服务器中的请求缓冲场景描述代码

Go语言如何判断两张图片的相似度

《Go语言如何判断两张图片的相似度》这篇文章主要为大家详细介绍了Go语言如何中实现判断两张图片的相似度的两种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 在介绍技术细节前,我们先来看看图片对比在哪些场景下可以用得到:图片去重:自动删除重复图片,为存储空间"瘦身"。想象你是一个

详解Linux中常见环境变量的特点与设置

《详解Linux中常见环境变量的特点与设置》环境变量是操作系统和用户设置的一些动态键值对,为运行的程序提供配置信息,理解环境变量对于系统管理、软件开发都很重要,下面小编就为大家详细介绍一下吧... 目录前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变

Go语言中Recover机制的使用

《Go语言中Recover机制的使用》Go语言的recover机制通过defer函数捕获panic,实现异常恢复与程序稳定性,具有一定的参考价值,感兴趣的可以了解一下... 目录引言Recover 的基本概念基本代码示例简单的 Recover 示例嵌套函数中的 Recover项目场景中的应用Web 服务器中

Java Multimap实现类与操作的具体示例

《JavaMultimap实现类与操作的具体示例》Multimap出现在Google的Guava库中,它为Java提供了更加灵活的集合操作,:本文主要介绍JavaMultimap实现类与操作的... 目录一、Multimap 概述Multimap 主要特点:二、Multimap 实现类1. ListMult