我想改进下面代码中的getCustomerFromDTO方法,我需要从接口{}创建一个 struct ,目前我需要将该接口封送到字节[],然后将数组解封到我的 struct 中——一定有更好的方法.

我的用例是,我通过rabbitmq发送 struct ,为了发送它们,我使用这个通用DTO包装器,它有关于它们的其他特定于域的数据.

type Customer struct {
    Name string `json:"name"`
}

type UniversalDTO struct {
    Data interface{} `json:"data"`
    // more fields with important meta-data about the message...
}

func main() {
    // create a customer, add it to DTO object and marshal it
    customer := Customer{Name: "Ben"}
    dtoToSend := UniversalDTO{customer}
    byteData, _ := json.Marshal(dtoToSend)

    // unmarshal it (usually after receiving bytes from somewhere)
    receivedDTO := UniversalDTO{}
    json.Unmarshal(byteData, &receivedDTO)

    //Attempt to unmarshall our customer
    receivedCustomer := getCustomerFromDTO(receivedDTO.Data)
    fmt.Println(receivedCustomer)
}

func getCustomerFromDTO(data interface{}) Customer {
    customer := Customer{}
    bodyBytes, _ := json.Marshal(data)
    json.Unmarshal(bodyBytes, &customer)
    return customer
}

推荐答案

在解组DTO之前,将Data字段设置为您期望的类型.

type Customer struct {
    Name string `json:"name"`
}

type UniversalDTO struct {
    Data interface{} `json:"data"`
    // more fields with important meta-data about the message...
}

func main() {
    // create a customer, add it to DTO object and marshal it
    customer := Customer{Name: "Ben"}
    dtoToSend := UniversalDTO{customer}
    byteData, _ := json.Marshal(dtoToSend)

    // unmarshal it (usually after receiving bytes from somewhere)
    receivedCustomer := &Customer{}
    receivedDTO := UniversalDTO{Data: receivedCustomer}
    json.Unmarshal(byteData, &receivedDTO)

    //done
    fmt.Println(receivedCustomer)
}

如果无法在DTO上的Data字段解组前对其进行初始化,则可以在解组后使用类型断言.encoding/json包将interface{}个类型值转换为map[string]interface{},因此代码如下所示:

type Customer struct {
    Name string `json:"name"`
}

type UniversalDTO struct {
    Data interface{} `json:"data"`
    // more fields with important meta-data about the message...
}

func main() {
    // create a customer, add it to DTO object and marshal it
    customer := Customer{Name: "Ben"}
    dtoToSend := UniversalDTO{customer}
    byteData, _ := json.Marshal(dtoToSend)

    // unmarshal it (usually after receiving bytes from somewhere)
    receivedDTO := UniversalDTO{}
    json.Unmarshal(byteData, &receivedDTO)

    //Attempt to unmarshall our customer
    receivedCustomer := getCustomerFromDTO(receivedDTO.Data)
    fmt.Println(receivedCustomer)
}

func getCustomerFromDTO(data interface{}) Customer {
    m := data.(map[string]interface{})
    customer := Customer{}
    if name, ok := m["name"].(string); ok {
        customer.Name = name
    }
    return customer
}

Go相关问答推荐

为什么使用append时Go切片的初始容量会随着int32和int64类型的不同而变化?

Google OAuth2没有刷新令牌

如何使用我的 struct 化日志(log)记录格式使人panic ?

在GO中使用泛型类型 struct 实现接口方法

通过代理从golang连接到ftp

关于如何使用 Service Weaver 设置多个不同侦听器的问题

如何从 nil 指针创建值

有没有办法让sqlc生成可以使用pgxpool的代码

使用Go和Operator SDK通过API调用设置Kubernetes Pods的安装步骤

Go time.Parse 无效的 ISO 日期

错误!在为 age-viewer-go 运行 wails dev 或 wails build 命令时

使用 golang 生成 vim

查找、解析和验证邮箱地址

如何将文件上传到 Google Drive,并与使用服务帐户和 Golang 的任何人共享

Golang Getrlimit 返回与 ulimit 不同的值

Golang - 无法从 pipped Windows 命令中获取结果

退格字符在围棋操场中不起作用

如何扩充 ResponseWriter 的 Header() 返回的 map

(如何)我可以基于接口抽象地实现Stringer吗?

获取单调时间,同 CLOCK_MONOTONIC