首页 > 其他分享 >golang类型转换模块之gconv

golang类型转换模块之gconv

时间:2024-02-07 17:13:17浏览次数:36  
标签:类型转换 struct gconv fmt golang func interface string

gf框架提供了非常强大的类型转换包gconv,可以实现将任何数据类型转换为指定的数据类型,对常用基本数据类型之间的无缝转换,同时也支持任意类型到struct对象的属性赋值。由于gconv模块内部大量使用了断言而非反射(仅struct转换使用到了反射),因此执行的效率非常高。

使用方式:

import "gitee.com/johng/gf/g/util/gconv"

方法列表: godoc.org/github.com/johng-cn/gf/g/util/gconv

// 基本类型
func Bool(i interface{}) bool
func Float32(i interface{}) float32
func Float64(i interface{}) float64
func Int(i interface{}) int
func Int16(i interface{}) int16
func Int32(i interface{}) int32
func Int64(i interface{}) int64
func Int8(i interface{}) int8
func String(i interface{}) string
func Uint(i interface{}) uint
func Uint16(i interface{}) uint16
func Uint32(i interface{}) uint32
func Uint64(i interface{}) uint64
func Uint8(i interface{}) uint8

// slice类型
func Bytes(i interface{}) []byte
func Ints(i interface{}) []int
func Floats(i interface{}) []float64
func Strings(i interface{}) []string
func Interfaces(i interface{}) []interface{}

// 时间类型
func Time(i interface{}, format ...string) time.Time
func TimeDuration(i interface{}) time.Duration

// 对象转换
func Struct(params interface{}, objPointer interface{}, attrMapping ...map[string]string) error

// 根据类型名称执行基本类型转换(非struct转换))
func Convert(i interface{}, t string, extraParams ...interface{}) interface{}

基本使用

常用基本类型的转换方法比较简单,我们这里使用一个例子来演示转换方法的使用及效果。

package main

import (
    "fmt"
    "gitee.com/johng/gf/g/util/gconv"
)

func main() {
    i := 123
    fmt.Printf("%10s %v\n", "Int:",        gconv.Int(i))
    fmt.Printf("%10s %v\n", "Int8:",       gconv.Int8(i))
    fmt.Printf("%10s %v\n", "Int16:",      gconv.Int16(i))
    fmt.Printf("%10s %v\n", "Int32:",      gconv.Int32(i))
    fmt.Printf("%10s %v\n", "Int64:",      gconv.Int64(i))
    fmt.Printf("%10s %v\n", "Uint:",       gconv.Uint(i))
    fmt.Printf("%10s %v\n", "Uint8:",      gconv.Uint8(i))
    fmt.Printf("%10s %v\n", "Uint16:",     gconv.Uint16(i))
    fmt.Printf("%10s %v\n", "Uint32:",     gconv.Uint32(i))
    fmt.Printf("%10s %v\n", "Uint64:",     gconv.Uint64(i))
    fmt.Printf("%10s %v\n", "Float32:",    gconv.Float32(i))
    fmt.Printf("%10s %v\n", "Float64:",    gconv.Float64(i))
    fmt.Printf("%10s %v\n", "Bool:",       gconv.Bool(i))
    fmt.Printf("%10s %v\n", "String:",     gconv.String(i))

    fmt.Printf("%10s %v\n", "Bytes:",      gconv.Bytes(i))
    fmt.Printf("%10s %v\n", "Strings:",    gconv.Strings(i))
    fmt.Printf("%10s %v\n", "Ints:",       gconv.Ints(i))
    fmt.Printf("%10s %v\n", "Floats:",     gconv.Floats(i))
    fmt.Printf("%10s %v\n", "Interfaces:", gconv.Interfaces(i))
}

执行后,输出结果为:

      Int: 123
     Int8: 123
    Int16: 123
    Int32: 123
    Int64: 123
     Uint: 123
    Uint8: 123
   Uint16: 123
   Uint32: 123
   Uint64: 123
  Float32: 123
  Float64: 123
     Bool: true
   String: 123
    Bytes: [123]
  Strings: [123]
     Ints: [123]
   Floats: [123]
Interfaces: [123]

Struct转换

项目中我们经常会遇到大量struct的使用,以及各种数据类型到struct的转换/赋值(特别是json/xml/各种协议编码转换的时候)。为提高编码及项目维护效率,gconv模块为各位开发者带来了极大的福利,为数据解析提供了更高的灵活度。

gconv模块执行struct转换的方法仅有一个,定义如下:

func Struct(params interface{}, objPointer interface{}, attrMapping ...map[string]string) error

其中:

  1. params为需要转换到struct的变量参数,可以为任意数据类型,常见的数据类型为map
  2. objPointer为需要执行转的目标struct对象,这个参数必须为该struct的对象指针,转换成功后该对象的属性将会更新;
  3. attrMapping为自定义的map键名strcut属性之间的映射关系,此时params参数必须为map类型,否则该参数无意义;

转换规则

gconv模块的struct转换特性非常强大,支持任意数据类型到struct属性的映射转换。在没有提供自定义attrMapping转换规则的情况下,默认的转换规则如下:

  1. struct中需要匹配的属性必须为公开属性(首字母大小);
  2. 根据params类型的不同,逻辑会有不同:

    • params参数为map: 键名会自动按照 不区分大小写 且 忽略-/_/空格符号 的形式与struct属性进行匹配;
    • params参数为其他类型: 将会把该变量值与struct的第一个属性进行匹配;
    • 此外,如果struct的属性为复杂数据类型如slice,map,strcut那么会进行递归匹配赋值;
  3. 如果匹配成功,那么将键值赋值给属性,如果无法匹配,那么忽略;

以下是几个匹配的示例:

map键名    struct属性     是否匹配
name       Name           match
Email      Email          match
nickname   NickName       match
NICKNAME   NickName       match
Nick-Name  NickName       match
nick_name  NickName       match
nick name  NickName       match
NickName   Nick_Name      match
Nick-name  Nick_Name      match
nick_name  Nick_Name      match
nick name  Nick_Name      match

示例1,基本使用

package main

import (
    "gitee.com/johng/gf/g"
    "gitee.com/johng/gf/g/util/gconv"
)

type User struct {
    Uid      int
    Name     string
    Site_Url string
    NickName string
    Pass1    string `gconv:"password1"`
    Pass2    string `gconv:"password2"`
}

func main() {
    user    := (*User)(nil)

    // 使用默认映射规则绑定属性值到对象
    user     = new(User)
    params1 := g.Map{
        "uid"       : 1,
        "Name"      : "john",
        "siteurl"   : "https://gfer.me",
        "nick_name" : "johng",
        "PASS1"     : "123",
        "PASS2"     : "456",
    }
    if err := gconv.Struct(params1, user); err == nil {
        g.Dump(user)
    }

    // 使用struct tag映射绑定属性值到对象
    user     = new(User)
    params2 := g.Map {
        "uid"       : 2,
        "name"      : "smith",
        "site-url"  : "https://gfer.me",
        "nick name" : "johng",
        "password1" : "111",
        "password2" : "222",
    }
    if err := gconv.Struct(params2, user); err == nil {
        g.Dump(user)
    }
}

可以看到,我们可以直接通过Struct方法将map按照默认规则绑定到struct上,也可以使用struct tag的方式进行灵活的设置。此外,Struct方法有第三个map参数,用于指定自定义的参数名称到属性名称的映射关系。

执行后,输出结果为:

{
    "Uid": 1,
    "Name": "john",
    "Site_Url": "https://gfer.me",
    "NickName": "johng",
    "Pass1": "123",
    "Pass2": "456"
}
{
    "Uid": 2,
    "Name": "smith",
    "Site_Url": "https://gfer.me",
    "NickName": "johng",
    "Pass1": "111",
    "Pass2": "222"
}

示例2,复杂类型转换

1. slice基本类型属性

package main

import (
    "gitee.com/johng/gf/g/util/gconv"
    "gitee.com/johng/gf/g"
    "fmt"
)

// 演示slice类型属性的赋值
func main() {
    type User struct {
        Scores []int
    }

    user   := new(User)
    scores := []interface{}{99, 100, 60, 140}

    // 通过map映射转换
    if err := gconv.Struct(g.Map{"Scores" : scores}, user); err != nil {
        fmt.Println(err)
    } else {
        g.Dump(user)
    }

    // 通过变量映射转换,直接slice赋值
    if err := gconv.Struct(scores, user); err != nil {
        fmt.Println(err)
    } else {
        g.Dump(user)
    }
}

执行后,输出结果为:

{
    "Scores": [
        99,
        100,
        60,
        140
    ]
}
{
    "Scores": [
        99,
        100,
        60,
        140
    ]
}

2. struct属性为struct

package main

import (
    "gitee.com/johng/gf/g/util/gconv"
    "gitee.com/johng/gf/g"
    "fmt"
)

func main() {
    type Score struct {
        Name   string
        Result int
    }
    type User struct {
        Scores Score
    }

    user   := new(User)
    scores := map[string]interface{}{
        "Scores" : map[string]interface{}{
            "Name"   : "john",
            "Result" : 100,
        },
    }

    // 嵌套struct转换
    if err := gconv.Struct(scores, user); err != nil {
        fmt.Println(err)
    } else {
        g.Dump(user)
    }
}

执行后,输出结果为:

{
    "Scores": {
        "Name": "john",
        "Result": 100
    }
}

3. struct属性为slice,数值为slice

package main

import (
    "gitee.com/johng/gf/g/util/gconv"
    "gitee.com/johng/gf/g"
    "fmt"
)

func main() {
    type Score struct {
        Name   string
        Result int
    }
    type User struct {
        Scores []Score
    }

    user   := new(User)
    scores := map[string]interface{}{
        "Scores" : []interface{}{
            map[string]interface{}{
                "Name"   : "john",
                "Result" : 100,
            },
            map[string]interface{}{
                "Name"   : "smith",
                "Result" : 60,
            },
        },
    }

    // 嵌套struct转换,属性为slice类型,数值为slice map类型
    if err := gconv.Struct(scores, user); err != nil {
        fmt.Println(err)
    } else {
        g.Dump(user)
    }
}

执行后,输出结果为:

{
    "Scores": [
        {
            "Name": "john",
            "Result": 100
        },
        {
            "Name": "smith",
            "Result": 60
        }
    ]
}

4. struct属性为slice,数值为非slice

package main

import (
    "gitee.com/johng/gf/g/util/gconv"
    "gitee.com/johng/gf/g"
    "fmt"
)

func main() {
    type Score struct {
        Name   string
        Result int
    }
    type User struct {
        Scores []Score
    }

    user   := new(User)
    scores := map[string]interface{}{
        "Scores" : map[string]interface{}{
            "Name"   : "john",
            "Result" : 100,
        },
    }

    // 嵌套struct转换,属性为slice类型,数值为map类型
    if err := gconv.Struct(scores, user); err != nil {
        fmt.Println(err)
    } else {
        g.Dump(user)
    }
}

执行后,输出结果为:

{
    "Scores": [
        {
            "Name": "john",
            "Result": 100
        }
    ]
}




标签:类型转换,struct,gconv,fmt,golang,func,interface,string
From: https://www.cnblogs.com/xingxia/p/18011078/golang_gconv

相关文章

  • 详解golang实现一个带时效的环形队列
    1.需求mysql执行时间超过100ms以上打warn日志,但是一分钟以内这种warn日志超过10条就需要告警。所以需求就是获得一分钟以内mysql的warn的个数。2.分析为什么使用环形队列而不使用slice?因为队列长度固定,所以可以一开始就分配好空间,不用自动扩容,环形的目的就是不用改变数组的值,只用移......
  • golang定时器之timer+ticker
    转载: https://juejin.cn/post/7327157426298011663 Timer是一个一次性的定时器,用于在未来的某一时刻执行一次操作。基本使用创建Timer定时器的方式有两种:NewTimer(dDuration)*Timer:该函数接受一个time.Duration类型的参数d(时间间隔),表示定时器在过期之前等待的......
  • golang之常用标准库汇总
    1.import"runtime/debug"func StackfuncStack()[]byteStack 返回格式化的go程的调用栈踪迹。 对于每一个调用栈,它包括原文件的行信息和PC值;对go函数还会尝试获取调用该函数的函数或方法,及调用所在行的文本。 func PrintStackfuncPrintStack()PrintStack将Stack......
  • golang命令行cobra学习
    varrootCmd=&cobra.Command{Use:"ferry",Short:"-v",SilenceUsage:true,DisableAutoGenTag:true,Long:`ferry`,Args:func(cmd*cobra.Command,args[]string)......
  • golang之设计模式
    [选项模式]packagemainimport"fmt"typeOptionFuncfunc(*DoSomethingOption)typeDoSomethingOptionstruct{aintbstringcbool}funcNewDoSomethingOption(cbool,opts...OptionFunc)*DoSomethingOption{s:=&DoSomethi......
  • 解决golang依赖库被删库问题
    调用的开源库引用了github个人仓库,如果作者删除了仓库或者改成私人仓库,那么gomodtidy就会失败以github.com/mitchellh/osext为例,作者因为某些原因删除了仓库,并给出了替代的官方仓库github.com/kardianos/osext使用replace命令gomodedit-replace[oldgitpackage]@[versi......
  • Golang Grpc-Gateway生成-buf版
    官网有个工具buf可以自动生成https://github.com/bufbuild/buf/releases按照自己的平台下载对应的文件,并把可执行文件加入到环境变量下proto同级目录下新增buf.gen.yaml或者执行bufmodinit,buf默认会扫描所有文件夹的*.proto,所以我在同级目录下创建version:v1plugins:-......
  • Golang Grpc-Gateway生成-基础版
    时间久了不用就会忘记指令,这里做个笔记创建一个文件//+buildtoolspackagetoolsimport(_"github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway"_"github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2"_"google.gol......
  • 数据类型转换
    publicclass类型转换{/*字节容量:byte、short、char-int-long-float-double(低——高)运算中,不同类型的数据先转换为同一类型,然后进行运算*///强制类型转换:高-低(类型)变量名publicstaticvoidmain(String[]args){inti=128;by......
  • go-carbon v2.3.8 发布,轻量级、语义化、对开发者友好的 golang 时间处理库
    carbon是一个轻量级、语义化、对开发者友好的golang时间处理库,支持链式调用。目前已被awesome-go收录,如果您觉得不错,请给个star吧github.com/golang-module/carbongitee.com/golang-module/carbon安装使用Golang版本大于等于1.16//使用github库goget-ugithu......