golang安全处理空类型与复杂结构数据转换插件库typ的使用
Golang安全处理空类型与复杂结构数据转换插件库Typ的使用
Typ是一个强大的Golang库,提供了安全转换和从内置类型获取数据的接口。
特性
- 安全转换内置类型:
bool
、int
、int8
、int16
、int32
、int64
、uint
、uint8
、uint16
、uint32
、uint64
、float32
、float64
、complex64
、complex128
、string
- 所有基本类型的空类型,支持接口:
json.Unmarshaler
、json.Marshaler
、sql.Scanner
、driver.Valuer
- 从接口中检索多维非结构化数据
- 通过接口(反射)和原生类型提供转换函数以获得更好的性能
- 一些人性化的字符串转换函数
安装
使用go get
安装最新版本的库:
go get -u github.com/gurukami/typ
然后在你的应用中引入包:
import "github.com/gurukami/typ/v2"
使用示例
从接口值转换为内置类型
// typ.Of(v interface{}, options ...Option).{Type}(defaultValue ...{Type})
//
// {Type}可以是:
// Bool,
// Int, Int8, Int16, Int32, Int64,
// Uint, Uint8, Uint16, Uint32, Uint64,
// Float32, Float,
// Complex64, Complex,
// String
//
// 所有转换方法返回{Type}Accessor,包含有用的方法:
// V() - 类型值
// Present() - 判断值是否已设置
// Valid() - 判断值是否有效(无错误)
// Err() error - 返回底层错误
// Set(value {Type}) - 保存值到当前结构
// Clone() {Type}Accessor - 返回带有保留值和错误的新实例
//
// Scan(value interface{}) | sql.Scanner
// Value() (driver.Value, error) | driver.Valuer
//
// UnmarshalJSON(b []byte) error | json.Unmarshaler
// MarshalJSON() ([]byte, error) | json.Marshaler
// 有效转换
nv := typ.Of(3.1415926535, typ.FmtByte('g'), typ.Precision(4)).String()
fmt.Printf("Value: %v, Valid: %v, Present: %v, Error: %v\n", nv.V(), nv.Valid(), nv.Present(), nv.Error)
// 输出: Value: 3.142, Valid: true, Present: true, Error: <nil>
// 无效转换
nv = typ.Of(3.1415926535).Int()
fmt.Printf("Value: %v, Valid: %v, Present: %v, Error: %v\n", nv.V(), nv.Valid(), nv.Present(), nv.Error)
// 输出: Value: 3, Valid: false, Present: true, Error: value can't safely convert
不使用反射的原生转换(已知类型时性能最佳)
// typ.{FromType}{ToType}(value , [options ...{FromType}{ToType}Option]).V()
//
// {FromType}, {ToType}可以是:
// Bool,
// Int, Int8, Int16, Int32, Int64,
// Uint, Uint8, Uint16, Uint32, Uint64,
// Float32, Float,
// Complex64, Complex,
// String
// 有效转换
nv := typ.FloatString(3.1415926535, typ.FloatStringFmtByte('g'), typ.FloatStringPrecision(4))
fmt.Printf("Value: %v, Valid: %v, Present: %v, Error: %v\n", nv.V(), nv.Valid(), nv.Present(), nv.Error)
// 输出: Value: 3.142, Valid: true, Present: true, Error: <nil>
// 无效转换
nv = typ.FloatInt(3.1415926535)
fmt.Printf("Value: %v, Valid: %v, Present: %v, Error: %v\n", nv.V(), nv.Valid(), nv.Present(), nv.Error)
// 输出: Value: 3, Valid: false, Present: true, Error: value can't safely convert
从接口中检索多维非结构化数据
data := map[int]interface{}{
0: []interface{}{
0: map[string]int{
"0": 42,
},
},
}
// 值存在
nv := typ.Of(data).Get(0, 0, "0").Interface()
fmt.Printf("Value: %v, Valid: %v, Present: %v, Error: %v\n", nv.V(), nv.Valid(), nv.Present(), nv.Error)
// 输出: Value: 42, Valid: true, Present: true, Error: <nil>
// 值不存在
nv = typ.Of(data).Get(3, 7, "5").Interface()
fmt.Printf("Value: %v, Valid: %v, Present: %v, Error: %v\n", nv.V(), nv.Valid(), nv.Present(), nv.Error)
// 输出: Value: <nil>, Valid: false, Present: false, Error: out of bounds on given data
安全类型转换规则
From / to | Bool | Int* | String | Uint* | Float* | Complex* |
---|---|---|---|---|---|---|
Bool | + | + | + | + | + | + |
Int* | + | + | formatting |
>= 0 |
24bit or 53bit |
real , 24bit or 53bit |
String | parsing |
parsing |
+ | parsing |
parsing |
parsing |
Uint* | + | 63bit |
formatting |
+ | 24bit or 53bit |
24bit or 53bit |
Float* | + | 24bit or 53bit |
formatting |
>= 0 , 24bit or 53bit |
+ | + |
Complex* | + | real , 24bit or 53bit |
+ | >= 0 , real , 24bit or 53bit |
real |
+ |
*基于位大小容量,Int
,Uint
为8,16,32,64
;Float
,Complex
为32,64
许可证
MIT许可证
版权所有 © 2019 Gurukami
更多关于golang安全处理空类型与复杂结构数据转换插件库typ的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang安全处理空类型与复杂结构数据转换插件库typ的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang 安全处理空类型与复杂结构数据转换 - typ 库使用指南
在 Go 语言中处理空类型(nil)和复杂结构数据转换时,typ 库是一个非常实用的工具,它提供了类型安全的转换方式。下面我将详细介绍如何使用 typ 库。
typ 库简介
typ 是一个轻量级的 Go 库,主要用于:
- 安全处理 nil 值
- 类型安全的转换
- 简化复杂结构的数据处理
- 提供默认值机制
安装 typ 库
go get github.com/goloop/typ
基本用法
1. 安全处理 nil 值
package main
import (
"fmt"
"github.com/goloop/typ"
)
func main() {
var s *string // nil 指针
// 安全获取值,如果为 nil 则返回默认值
val := typ.Or(s, "default")
fmt.Println(val) // 输出: default
// 或者从 nil 指针中安全获取值
val2 := typ.Val(s).Or("default")
fmt.Println(val2) // 输出: default
}
2. 类型安全转换
package main
import (
"fmt"
"github.com/goloop/typ"
)
func main() {
// 安全转换为字符串
str := typ.String(123)
fmt.Println(str) // 输出: "123"
// 安全转换为整数
num := typ.Int("42")
fmt.Println(num) // 输出: 42
// 转换失败时使用默认值
num2 := typ.Int("abc", 100) // 第二个参数是默认值
fmt.Println(num2) // 输出: 100
}
3. 处理复杂结构
package main
import (
"fmt"
"github.com/goloop/typ"
)
type User struct {
Name string
Age int
}
func main() {
// 从 map 安全创建结构体
data := map[string]interface{}{
"Name": "Alice",
"Age": 25,
}
var user User
err := typ.Decode(data, &user)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Printf("%+v\n", user) // 输出: {Name:Alice Age:25}
// 处理嵌套结构
data2 := map[string]interface{}{
"Name": "Bob",
"Age": "30", // 字符串形式的数字
"Meta": map[string]interface{}{
"Role": "Admin",
},
}
var user2 struct {
Name string
Age int
Meta struct {
Role string
}
}
err = typ.Decode(data2, &user2)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Printf("%+v\n", user2) // 输出: {Name:Bob Age:30 Meta:{Role:Admin}}
}
4. JSON 安全处理
package main
import (
"fmt"
"github.com/goloop/typ"
)
func main() {
// 安全解析 JSON
jsonStr := `{"name":"Charlie","age":28}`
var result map[string]interface{}
err := typ.JsonDecode([]byte(jsonStr), &result)
if err != nil {
fmt.Println("Error:", err)
return
}
name := typ.String(result["name"])
age := typ.Int(result["age"])
fmt.Printf("Name: %s, Age: %d\n", name, age)
// 处理可能不存在的字段
email := typ.String(result["email"], "no-email@example.com")
fmt.Println("Email:", email)
}
高级用法
1. 自定义转换器
package main
import (
"fmt"
"github.com/goloop/typ"
)
type Status int
const (
StatusActive Status = iota
StatusInactive
)
func main() {
// 注册自定义转换器
typ.RegisterConverter(func(v interface{}) (Status, bool) {
s, ok := typ.String(v).Data()
if !ok {
return StatusInactive, false
}
switch s {
case "active":
return StatusActive, true
case "inactive":
return StatusInactive, true
default:
return StatusInactive, false
}
})
// 使用自定义转换器
status := typ.Convert[Status]("active").Or(StatusInactive)
fmt.Println(status) // 输出: 0 (StatusActive)
}
2. 链式调用
package main
import (
"fmt"
"github.com/goloop/typ"
)
func main() {
// 链式调用处理数据
result := typ.Of("123").
Int(). // 转换为 int
Filter(func(v int) bool { return v > 100 }). // 过滤
Or(100). // 如果过滤失败则返回 100
Add(50). // 加 50
Data() // 获取最终结果
fmt.Println(result) // 输出: 150
}
最佳实践
-
始终处理错误:即使 typ 提供了安全机制,也要检查关键操作的错误
-
合理使用默认值:为关键数据设置合理的默认值
-
类型断言前使用 typ:替代直接的类型断言,更安全
-
处理外部数据时优先使用 typ:如 JSON、YAML 解析等场景
typ 库通过提供类型安全的转换和 nil 值处理,大大简化了 Go 程序中的数据转换和处理逻辑,特别是在处理来自外部的不确定数据时非常有用。