Go語言泛型打造優(yōu)雅的切片工具庫
什么是泛型
泛型是一種編程范式,允許開發(fā)者在編寫代碼時定義通用的類型參數(shù),而不是具體的類型。通過泛型,可以編寫出能夠處理多種數(shù)據(jù)類型的代碼,而無需為每種類型重復編寫相同的邏輯。例如,一個泛型函數(shù)可以同時處理整數(shù)、浮點數(shù)、字符串等多種類型的數(shù)據(jù)。
泛型解決了什么問題
在 Go 語言引入泛型之前,開發(fā)者在處理不同數(shù)據(jù)類型時,往往需要編寫重復的代碼。例如,實現(xiàn)一個排序算法,可能需要為整數(shù)、浮點數(shù)、字符串等分別編寫不同的版本。這種重復不僅增加了代碼量,也降低了代碼的可維護性。引入泛型后,可以通過定義一個通用的類型參數(shù),編寫一個通用的排序函數(shù),從而提高代碼的復用性和可維護性。
基于泛型的常見切片操作
博主結合自身在實際開發(fā)當中的經(jīng)驗,將利用Go泛型,封裝一些常見的切片操作。本篇博客所編寫的代碼,皆可直接集成到生產環(huán)境的公共代碼庫中。各位小伙伴可以根據(jù)自身項目的實際情況,將對你們項目有幫助的代碼遷移到自己的項目當中。
1.反轉切片(改變原切片)
func ReverseOriginalSlice[T any](s []T) {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}
2.反轉切片(不改變原切片)
func ReverseSlice[T any](s []T) []T {
res := make([]T, len(s))
copy(res, s)
ReverseOriginalSlice(res) // 調用之前的ReverseOriginalSlice函數(shù)
return res
}
3.切片分批
func BatchSlice[T any](s []T, size int) [][]T {
var batchSlice [][]T
// 遍歷切片,每次取 size 個元素
for i := 0; i < len(s); i += size {
end := i + size
// 處理最后一批元素數(shù)量不足 size 的情況
if end > len(s) {
end = len(s)
}
// 將當前批次的元素添加到結果中
batchSlice = append(batchSlice, s[i:end])
}
return batchSlice
}
4.合并切片
func MergeSlices[T any](slices ...[]T) []T {
totalLength := 0
for _, slice := range slices {
totalLength += len(slice)
}
res := make([]T, 0, totalLength)
for _, slice := range slices {
ls := make([]T, len(slice))
copy(ls, slice)
res = append(res, ls...)
}
return res
}
5.切片去重
func UniqueSlice[T comparable](s []T) []T {
seen := make(map[T]bool)
res := make([]T, 0, len(s))
for _, v := range s {
if !seen[v] {
// 如果元素未出現(xiàn)過,添加到結果切片中
res = append(res, v)
seen[v] = true
}
}
return res
}
6.切片轉哈希表
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
}
7.哈希表轉切片
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
}
8.獲取切片元素的某個字段
func GetListField[T any, V any](s []T, fieldFunc func(T) V) []V {
res := make([]V, 0, len(s))
for _, item := range s {
res = append(res, fieldFunc(item))
}
return res
}
9.切片全部元素滿足條件判斷
func SliceMatchCondition[T any](s []T, condition func(T) bool) bool {
for _, v := range s {
if !condition(v) {
return false
}
}
return true
}
10.取切片交集
func Intersection[T comparable](slices ...[]T) []T {
if len(slices) == 0 {
return nil
}
// 使用 map 來存儲第一個切片中的元素
intersectionMap := make(map[T]int)
for _, v := range slices[0] {
intersectionMap[v]++
}
// 遍歷后續(xù)切片,更新交集
for _, slice := range slices[1:] {
m := make(map[T]int)
for _, v := range slice {
if _, exists := intersectionMap[v]; exists {
m[v]++
}
}
intersectionMap = m
}
// 將交集的元素收集到結果切片中
var res []T
for k := range intersectionMap {
res = append(res, k)
}
return res
}
11.取切片并集
func Union[T comparable](slices ...[]T) []T {
elementMap := make(map[T]struct{})
for _, slice := range slices {
for _, v := range slice {
elementMap[v] = struct{}{}
}
}
var res []T
for k := range elementMap {
res = append(res, k)
}
return res
}
代碼合集
我將上述所有代碼集成到一個slices.go文件當中。如果各位小伙伴們的項目有需要,只需將以下代碼完整拷貝到你們項目的基礎代碼工具庫即可。
slices.go
package slices
// 反轉切片(改變原切片)
func ReverseOriginalSlice[T any](s []T) {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}
// 反鉆切片(不改變原切片)
func ReverseSlice[T any](s []T) []T {
res := make([]T, len(s))
copy(res, s)
ReverseOriginalSlice(res)
return res
}
// 切片分批
func BatchSlice[T any](s []T, size int) [][]T {
var batchSlice [][]T
for i := 0; i < len(s); i += size {
end := i + size
if end > len(s) {
end = len(s)
}
batchSlice = append(batchSlice, s[i:end])
}
return batchSlice
}
// 合并切片
func MergeSlices[T any](slices ...[]T) []T {
totalLength := 0
for _, slice := range slices {
totalLength += len(slice)
}
res := make([]T, 0, totalLength)
for _, slice := range slices {
ls := make([]T, len(slice))
copy(ls, slice)
res = append(res, ls...)
}
return res
}
// 切片去重
func UniqueSlice[T comparable](s []T) []T {
seen := make(map[T]bool)
res := make([]T, 0, len(s))
for _, v := range s {
if !seen[v] {
res = append(res, v)
seen[v] = true
}
}
return res
}
// 切片轉哈希表
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
}
// 哈希表轉切片
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
}
// 獲取切片元素的某個字段
func GetListField[T any, V any](s []T, fieldFunc func(T) V) []V {
res := make([]V, 0, len(s))
for _, item := range s {
res = append(res, fieldFunc(item))
}
return res
}
// 切片全部元素滿足條件判斷
func SliceMatchCondition[T any](s []T, condition func(T) bool) bool {
for _, v := range s {
if !condition(v) {
return false
}
}
return true
}
// 取切片交集
func Intersection[T comparable](slices ...[]T) []T {
if len(slices) == 0 {
return nil
}
intersectionMap := make(map[T]int)
for _, v := range slices[0] {
intersectionMap[v]++
}
for _, slice := range slices[1:] {
m := make(map[T]int)
for _, v := range slice {
if _, exists := intersectionMap[v]; exists {
m[v]++
}
}
intersectionMap = m
}
var res []T
for k := range intersectionMap {
res = append(res, k)
}
return res
}
// 取切片并集
func Union[T comparable](slices ...[]T) []T {
elementMap := make(map[T]struct{})
for _, slice := range slices {
for _, v := range slice {
elementMap[v] = struct{}{}
}
}
var res []T
for k := range elementMap {
res = append(res, k)
}
return res
}
總結
本文使用Go泛型,對常見的切片操作進行了封裝,整理出了一個切片工具庫slices.go。
到此這篇關于Go語言泛型打造優(yōu)雅的切片工具庫的文章就介紹到這了,更多相關Go泛型內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Go實現(xiàn)自動解壓縮包以及讀取docx/doc文件內容詳解
在開發(fā)過程中,我們常常需要處理壓縮包和文檔文件。本文將介紹如何使用Go語言自動解壓縮包和讀取docx/doc文件,需要的可以參考一下2023-03-03
Golang高性能持久化解決方案BoltDB數(shù)據(jù)庫介紹
這篇文章主要為大家介紹了Golang高性能持久化解決方案BoltDB數(shù)據(jù)庫介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步2021-11-11

