golang灵活数据类型处理插件库generic的使用
Golang灵活数据类型处理插件库Generic的使用
Generic是一个Go语言的灵活数据类型处理库,支持Go 1.12+版本。
安装
使用标准的go get
命令安装:
go get -u github.com/usk81/generic/v2
使用示例
编码/解码示例
package main
import (
"encoding/json"
"github.com/usk81/generic/v2"
)
type User struct {
Name string `json:"name"`
Age generic.Int `json:"age"`
}
func main() {
// 示例1:JSON字符串中包含数字字符串
var user1 User
u1 := []byte(`{"name":"Daryl Dixon","age":"40"}`)
json.Unmarshal(u1, &user1)
b, _ := json.Marshal(user1)
println(string(b))
// 输出: {"name":"Daryl Dixon","age":40}
// 示例2:JSON字符串中缺少字段
var user2 User
u2 := []byte(`{"name":"Rick Grimes"}`)
json.Unmarshal(u2, &user2)
b, _ = json.Marshal(user2)
println(string(b))
// 输出: {"name":"Rick Grimes","age":null}
}
数据类型转换示例
package main
import (
"fmt"
"github.com/usk81/generic"
)
func main() {
v := 1.0
// Bool类型转换
var tb generic.Bool
tb.Set(v)
vb := tb.Weak()
fmt.Printf("%v, (%T)\n", vb, vb)
// 输出: true, (bool)
// Float类型转换
var tf generic.Float
tf.Set(v)
vf := tf.Weak()
fmt.Printf("%v, (%T)\n", vf, vf)
// 输出: 1, (float64)
// Int类型转换
var ti generic.Int
ti.Set(v)
vi := ti.Weak()
fmt.Printf("%v, (%T)\n", vi, vi)
// 输出: 1, (int64)
// String类型转换
var ts generic.String
ts.Set(v)
vs := ts.Weak()
fmt.Printf("%v, (%T)\n", vs, vs)
// 输出: 1, (string)
// Time类型转换
var tt generic.Time
tt.Set(v)
vt := tt.Weak()
fmt.Printf("%v, (%T)\n", vt.UTC(), vt)
// 输出: 1970-01-01 09:00:01 +0900 JST, (time.Time)
// Uint类型转换
var tu generic.Uint
tu.Set(v)
vu := tu.Weak()
fmt.Printf("%v, (%T)\n", vu, vu)
// 输出: 1, (uint64)
}
性能基准测试
Generic库提供了多种数据类型的性能基准测试结果:
Marshal性能
Bool类型
版本 | 请求数 | ns/op | B/op | allocs/op |
---|---|---|---|---|
1.0.0 | 5,000,000 | 240 | 185 | 3 |
2.0.0 | 200,000,000 | 6.69 | 0 | 0 |
Float类型
版本 | 请求数 | ns/op | B/op | allocs/op |
---|---|---|---|---|
1.0.0 | 3,000,000 | 425 | 192 | 3 |
2.0.0 | 5,000,000 | 260 | 64 | 3 |
Int类型
版本 | 请求数 | ns/op | B/op | allocs/op |
---|---|---|---|---|
1.0.0 | 5,000,000 | 265 | 192 | 3 |
2.0.0 | 20,000,000 | 70.5 | 16 | 2 |
String (小文本)
版本 | 请求数 | ns/op | B/op | allocs/op |
---|---|---|---|---|
1.0.0 | 3,000,000 | 382 | 200 | 3 |
2.0.0 | 20,000,000 | 89.0 | 128 | 2 |
String (大文本)
版本 | 请求数 | ns/op | B/op | allocs/op |
---|---|---|---|---|
1.0.0 | 1,000,000 | 1056 | 776 | 4 |
2.0.0 | 5,000,000 | 237 | 896 | 2 |
许可证
MIT许可证
作者
Yusuke Komatsu
更多关于golang灵活数据类型处理插件库generic的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang灵活数据类型处理插件库generic的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang 泛型(generic)数据处理插件库使用指南
Go 1.18 引入的泛型(generic)特性极大地增强了 Go 语言处理灵活数据类型的能力。下面我将介绍如何使用 Go 泛型来处理各种数据类型。
基础泛型使用
1. 基本泛型函数
package main
import "fmt"
// 泛型函数,可以处理任意可比较类型
func Contains[T comparable](slice []T, item T) bool {
for _, v := range slice {
if v == item {
return true
}
}
return false
}
func main() {
// 用于int类型
intSlice := []int{1, 2, 3, 4, 5}
fmt.Println(Contains(intSlice, 3)) // true
// 用于string类型
strSlice := []string{"a", "b", "c"}
fmt.Println(Contains(strSlice, "d")) // false
}
2. 泛型结构体
type Stack[T any] struct {
items []T
}
func (s *Stack[T]) Push(item T) {
s.items = append(s.items, item)
}
func (s *Stack[T]) Pop() T {
if len(s.items) == 0 {
panic("stack is empty")
}
item := s.items[len(s.items)-1]
s.items = s.items[:len(s.items)-1]
return item
}
func main() {
intStack := Stack[int]{}
intStack.Push(1)
intStack.Push(2)
fmt.Println(intStack.Pop()) // 2
stringStack := Stack[string]{}
stringStack.Push("hello")
stringStack.Push("world")
fmt.Println(stringStack.Pop()) // "world"
}
高级泛型应用
1. 类型约束
import "golang.org/x/exp/constraints"
// Number 约束,限制为所有数字类型
type Number interface {
constraints.Integer | constraints.Float
}
func Sum[T Number](numbers []T) T {
var total T
for _, num := range numbers {
total += num
}
return total
}
func main() {
ints := []int{1, 2, 3}
fmt.Println(Sum(ints)) // 6
floats := []float64{1.1, 2.2, 3.3}
fmt.Println(Sum(floats)) // 6.6
}
2. 泛型Map/Filter/Reduce
// Map 对切片中的每个元素应用函数
func Map[T, U any](slice []T, f func(T) U) []U {
result := make([]U, len(slice))
for i, v := range slice {
result[i] = f(v)
}
return result
}
// Filter 过滤切片元素
func Filter[T any](slice []T, f func(T) bool) []T {
var result []T
for _, v := range slice {
if f(v) {
result = append(result, v)
}
}
return result
}
func main() {
numbers := []int{1, 2, 3, 4, 5}
// 平方
squares := Map(numbers, func(n int) int {
return n * n
})
fmt.Println(squares) // [1 4 9 16 25]
// 过滤偶数
evens := Filter(numbers, func(n int) bool {
return n%2 == 0
})
fmt.Println(evens) // [2 4]
}
实用泛型工具库
1. 通用转换函数
// ToPtr 返回值的指针
func ToPtr[T any](v T) *T {
return &v
}
// Deref 安全解引用指针
func Deref[T any](p *T) T {
if p == nil {
var zero T
return zero
}
return *p
}
func main() {
num := 42
ptr := ToPtr(num)
fmt.Println(*ptr) // 42
var nilPtr *int
fmt.Println(Deref(nilPtr)) // 0
}
2. 通用JSON处理
import "encoding/json"
// FromJSON 泛型JSON解析
func FromJSON[T any](data []byte) (T, error) {
var v T
err := json.Unmarshal(data, &v)
return v, err
}
// ToJSON 泛型JSON编码
func ToJSON[T any](v T) ([]byte, error) {
return json.Marshal(v)
}
func main() {
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
jsonData := []byte(`{"name":"Alice","age":30}`)
p, err := FromJSON[Person](jsonData)
if err != nil {
panic(err)
}
fmt.Println(p.Name) // Alice
newData, err := ToJSON(p)
fmt.Println(string(newData)) // {"name":"Alice","age":30}
}
注意事项
- 泛型会增加编译时间,适度使用
- 不是所有场景都需要泛型,简单场景用接口可能更合适
- 类型约束要合理设计,避免过度约束
- 运行时类型信息有限,无法进行反射类型检查
Go 泛型为数据处理提供了强大的工具,合理使用可以大幅减少重复代码,提高类型安全性。