Golang:不同结构类型之间的转换是否可能?

时间:2014-07-07 14:40:38

标签: struct go

假设我有两种类似的类型:

type type1 []struct {
    Field1 string
    Field2 int
}
type type2 []struct {
    Field1 string
    Field2 int
}

是否有直接的方法将值从type1写入type2,知道它们具有相同的字段? (除了编写一个将所有字段从源复制到目标的循环外)

感谢。

6 个答案:

答案 0 :(得分:45)

要提及OneOfOne的答案,请参阅规范的Conversions部分。

它声明

  

非常量值x可以在任何这些中转换为T类型   例:

     
      
  • x可分配给T
  •   
  • x的类型和T具有相同的基础类型。
  •   
  • x'类型和T是未命名的指针类型,它们的指针基类型具有相同的基础类型。
  •   
  • x'类型和T都是整数或浮点类型。
  •   
  • x的类型和T都是复杂类型。
  •   
  • x是一个整数或一个字节或符文切片,T是一个字符串类型。
  •   
  • x是一个字符串,T是一个字节或符文切片。
  •   

第一个也是突出显示的案例就是你的情况。两种类型都有基础类型

[]struct { Field1 string Field2 int }

基础类型定义为

  

如果T是预先声明的布尔,数字或字符串类型之一或类型文字,则相应的基础类型本身为T。否则,T的基础类型是T在其类型声明中引用的类型的基础类型。 (spec,Types

您正在使用类型文字来定义类型,因此此类型文字是您的基础类型。

答案 1 :(得分:31)

对于您的具体示例,您可以轻松地将其转换为playground

t1 := type1{{"A", 1}, {"B", 2}}
t2 := type2(t1)
fmt.Println(t2)

答案 2 :(得分:12)

从Go 1.8开始,将值从一种结构类型转换为另一种结构类型时,将忽略结构标记。在Go版本中,类型type1和type2将是可转换的,无论它们的struct标记如何。 https://beta.golang.org/doc/go1.8#language

答案 3 :(得分:2)

您可以手动使用映射器函数,该函数将t1类型的每个元素映射到t2类型。它会工作。

func GetT2FromT1(ob1 *t1) *t2 {
     ob2 := &t2 { Field1: t1.Field1, }
     return ob2
}

答案 4 :(得分:0)

只要结构具有相同的字段(带有encoding/json)和相同的基本类型,就可以尝试json:"name"来编组和取消编组结构。

package main

import (
    "encoding/json"
    "fmt"
)

type common struct {
    INT int
}

type A struct {
    XX  []int
    ZZ  []common
    T_T int `json:"qaq"`
}

type B struct {
    XX  []int
    ZZ  []common
    QAQ int32 `json:"qaq"`
}

func main() {
    a := A{
        XX: []int{1, 2, 3},
        ZZ: []common{
            common{0},
            common{1},
        },
        T_T: 5,
    }

    bs, _ := json.Marshal(a)
    b := new(B)
    json.Unmarshal(bs, b)
    fmt.Printf("a: %+v\n", a)
    fmt.Printf("b: %+v\n", *b)

}
➜  convert go run main.go
a: {XX:[1 2 3] ZZ:[{INT:0} {INT:1}] T_T:5}
b: {XX:[1 2 3] ZZ:[{INT:0} {INT:1}] QAQ:5}

答案 5 :(得分:0)

这不是标准方法,但是如果您希望有一种灵活的方法将结构转换为映射,或者如果您想在不使用 ` 的情况下摆脱结构的某些属性 json:"-",你可以使用JSON marshal

具体来说,这就是我所做的:

type originalStruct []struct {
    Field1 string
    Field2 int
}

targetStruct := make(map[string]interface{}) // `targetStruct` can be anything of your choice

temporaryVariable, _ := json.Marshal(originalStruct)
err = json.Unmarshal(temporaryVariable, &targetStruct) 
if err != nil {
    // Catch the exception to handle it as per your need
}

可能看起来像一个黑客,但在我的大部分任务中都非常有用。