Go 常用数据类型相互转换

729 阅读4分钟

简介

在日常的开发中,经常需要进行数据类型的类型(例如:将 struct 转换为 map 类型等),在遇到类型的转换的时候,大部分人都会有有没有库方法或需要自己去编写转换逻辑的疑问?以下通过介绍常用的类型之间相互转换的方法,来解答困惑。

常见类型转换

struct 类型与 interface{} 类型相互转换

  • interface{} 类型转换为 struct 类型

    通过 x.(T) 进行类型的转换

    // Event 事件结构体
    type Event struct {
       ID   string `json:"id"`
       Name string `json:"name"`
    }
    
    // InterfaceToStruct interface 类型转换为 struct 类型
    func InterfaceToStruct(i interface{}) error {
       // Interface to Struct
       event, ok := i.(Event)
       if !ok {
          return fmt.Errorf("interface:%+v to struct:%T fail", i, Event{})
       }
       fmt.Printf("interface:%+v to struct:%+v", i, event)
       return nil
    }
    
  • interface{} 类型转换为 struct 类型

    interface{}可以代表任意类型,则可以直接将struct赋值给interface{}类型进行类型的转换

    package main
    
    import (
       "fmt"
    )
    
    // Event 事件结构体
    type Event struct {
       ID   string `json:"id"`
       Name string `json:"name"`
    }
    
    func main() {
       event := Event{
          ID:   "001",
          Name: "Interface to Struct",
       }
      
       // struct to interface
       var i interface{} = event
       fmt.Printf("struct:%+v to interface:%+v", event, i)
    }
    

struct 类型与 map 类型相互转换

  • struct 类型转换为 map 类型

    使用第三方库

    利用第三方开源库(github.com/fatih/struc… 进行转换

    // Event 事件结构体
    type Event struct {
       ID   string `json:"id"`
       Name string `json:"name"`
    }
    
    var event = Event{
       ID:   "001",
       Name: "struct to map",
    }
    
    // struct to map
    m := structs.Map(event)
    

    自己实现

    利用反射遍历 struct 的 key 和 value,并将其赋值到 map 数据结构中

    // Event 事件结构体
    type Event struct {
       ID   string `json:"id"`
       Name string `json:"name"`
    }
    
    // StructToMap struct 类型转换为 map 类型
    func StructToMap(s interface{}) map[string]interface{} {
       if s == nil {
          return nil
       }
       m := make(map[string]interface{})
       t := reflect.TypeOf(s)
       v := reflect.ValueOf(s)
       for k := 0; k < t.NumField(); k++ {
          m[t.Field(k).Name] = v.Field(k).Interface()
       }
       return m
    }
    
    var event = Event{
       ID:   "001",
       Name: "struct to map",
    }
    // struct to map
    m := StructToMap(event)
    
  • map 类型转换为 struct 类型

    使用第三方库

    利用第三方库(github.com/mitchellh/m… ,进行转换

    // Event 事件结构体
    type Event struct {
       ID   string `json:"id"`
       Name string `json:"name"`
    }
    
    var m = map[string]string{
       "id":   "001",
       "name": "map to struct",
    }
    
    var event Event
    // map to struct
    mapstructure.Decode(m, &event)
    

    自己实现

    通过遍历 map 的 key 和 value,利用反射进行 struct 的赋值

    // Event 事件结构体
    type Event struct {
       ID   string `json:"id"`
       Name string `json:"name"`
    }
    
    // MapToStruct Map 数据类型转换为 Struct 数据类型
    func MapToStruct(m map[string]interface{}, s interface{}) error {
       structValue := reflect.ValueOf(s).Elem()
       for mKey, mValue := range m {
          structFieldValue := structValue.FieldByName(mKey)
          if !structFieldValue.IsValid() {
             return fmt.Errorf("no such field:%s in struct:%+v", mKey, s)
          }
          if !structFieldValue.CanSet() {
             return fmt.Errorf("cannot set field mValue:%s, in struct:%+v", mKey, s)
          }
          if structFieldValue.Type() != reflect.ValueOf(mValue).Type() {
             return fmt.Errorf("map value type didn't match struct field type")
          }
          structFieldValue.Set(reflect.ValueOf(mValue))
       }
       return nil
    }
    
    var m = map[string]interface{}{
       "ID":   "001",
       "Name": "map to struct",
    }
    var event Event
    if err := MapToStruct(m, &event); err != nil {
    fmt.Printf("map to struct err:%+v.", err)
    }
    

Struct 类型与 Json 类型相互转换

  • Struct 类型转换为 Json 类型

    通过基础库 encoding/json 的 Marshal 方法,将 struct 类型转换为 json 类型

    package main
    
    import (
       "encoding/json"
       "fmt"
    )
    
    // Event 事件结构体
    type Event struct {
       ID   string `json:"id"`
       Name string `json:"name"`
    }
    
    func main() {
       event := &Event{
          ID:   "001",
          Name: "struct to json",
       }
       // struct to json
       b, err := json.Marshal(event)
       if err != nil {
          fmt.Errorf("struct:%+v to json err:%+v", event, err)
       }
       fmt.Printf("struct to json result:%+v.", string(b))
    }
    
  • Json 类型转换为 Struct 类型

    通过基础库 encoding/json 的 Unmarshal 方法,将 json 类型转换为 struct 类型

    package main
    
    import (
       "encoding/json"
       "fmt"
    )
    
    // Event 事件结构体
    type Event struct {
       ID   string `json:"id"`
       Name string `json:"name"`
    }
    
    func main() {
       jsonStr := `{"id": "001", "name": "Json to Struct"}`
       var event Event
       // json to struct
       if err := json.Unmarshal([]byte(jsonStr), &event); err != nil {
          fmt.Errorf("json:%+v to struct err:%+v", event, err)
       }
       fmt.Printf("json to struct result:%+v", event)
    }
    

Map 类型转换与 Json 类型相互转换

  • Json 类型转换为 Map 类型

    通过基础库 encoding/json 的 Marshal 方法,将 Map 类型转换为 Struct 类型

    package main
    
    import (
       "encoding/json"
       "fmt"
    )
    
    func main() {
       event := map[string]interface{}{
          "id":   "001",
          "name": "Map to Json",
       }
       // map to json
       b, err := json.Marshal(event)
       if err != nil {
          fmt.Errorf("map:%+v to json err:%+v", event, err)
       }
       fmt.Printf("map to json result:%+v", string(b))
    }
    
  • Map 类型转换为 Json 类型

    通过基础库 encoding/json 的 Unmarshal 方法,将 json 类型转换为 map 类型

    package main
    
    import (
       "encoding/json"
       "fmt"
    )
    
    func main() {
       jsonStr := `{"id": "001", "name": "Json to Struct"}`
       var event map[string]interface{}
       // json to map
       if err := json.Unmarshal([]byte(jsonStr), &event); err != nil {
          fmt.Errorf("json:%+v to map err:%+v", event, err)
       }
       fmt.Printf("json to map result:%+v", event)
    }
    

interface{} 类型与 string 类型相互转换

  • interface{} 类型转换为 string 类型 将 interface{} 类型转换为 string 类型,分以下两种情况

image.png 情况1: interface{} 原始数据类型为 string 类型,转换为 string 类型,则通过x.(T)则可以进行转换

var str interface{} = "string"
// interface{} to string
fmt.Printf("%s", str.(string))

情况2: interface{} 原始数据类型非 string 类型,若通过x.(T)转换为string类型会报错,则需要通过fmt.Sprintf("%v", value)进行转换

mapValues := map[string]interface{}{
   "ID":   100,
   "Name": "Interface to string",
}

var arrayValues []string
for _, value := range mapValues {
   // interface to string
   str := fmt.Sprintf("%v", value)
   arrayValues = append(arrayValues, str)
}