本文主要是介绍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操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!