golang安全处理空类型与复杂结构数据转换插件库typ的使用

Golang安全处理空类型与复杂结构数据转换插件库Typ的使用

Typ是一个强大的Golang库,提供了安全转换和从内置类型获取数据的接口。

特性

  • 安全转换内置类型:boolintint8int16int32int64uintuint8uint16uint32uint64float32float64complex64complex128string
  • 所有基本类型的空类型,支持接口:json.Unmarshalerjson.Marshalersql.Scannerdriver.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,Uint8,16,32,64Float,Complex32,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
}

最佳实践

  1. 始终处理错误:即使 typ 提供了安全机制,也要检查关键操作的错误

  2. 合理使用默认值:为关键数据设置合理的默认值

  3. 类型断言前使用 typ:替代直接的类型断言,更安全

  4. 处理外部数据时优先使用 typ:如 JSON、YAML 解析等场景

typ 库通过提供类型安全的转换和 nil 值处理,大大简化了 Go 程序中的数据转换和处理逻辑,特别是在处理来自外部的不确定数据时非常有用。

回到顶部