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}
}

注意事项

  1. 泛型会增加编译时间,适度使用
  2. 不是所有场景都需要泛型,简单场景用接口可能更合适
  3. 类型约束要合理设计,避免过度约束
  4. 运行时类型信息有限,无法进行反射类型检查

Go 泛型为数据处理提供了强大的工具,合理使用可以大幅减少重复代码,提高类型安全性。

回到顶部