Go 之结构体/切片/Map 字段拷贝 copier

使用 github.com/jinzhu/copier 进行结构体数据拷贝

1. 介绍

在 Go 语言开发中,我们经常需要在不同的结构体之间复制数据。例如:

  • 复制数据库模型到 DTO(数据传输对象)
  • 复制请求参数到业务层对象
  • 复制多个字段的结构体到另一个结构体
  • gRPC .proto 文件生成的结构体自带内置字段导致用户自定义字段赋值繁琐

如果手动复制,每个字段都需要显式赋值,代码冗长且容易出错。因此,我们可以使用 jinzhu/copier 这个第三方库来简化这个过程。

地址:GitHub - jinzhu/copier: Copier for golang, copy value from struct to struct and more

2. copier 解决的问题

  • 减少冗余代码:无需手动赋值每个字段。
  • 支持结构体到结构体的拷贝:即使目标结构体的字段是源结构体的子集或超集。
  • 支持指针和非指针类型:能够处理 struct*struct 之间的转换。
  • 支持字段名相同的映射:只会拷贝名称匹配的字段。
  • **支持 **** 到 **:可以将 map[string]interface{} 复制到结构体。

3. 安装 copier

go get github.com/jinzhu/copier

4. 使用示例

4.1 结构体到结构体的拷贝

PS:使用过 gRPC 中 .proto 文件定义的结构体默认自带三个内置字段,剩余用户自定义字段赋值通过这种方式简直不要太爽

package main

import (
	"fmt"
	"github.com/jinzhu/copier"
)

type User struct {
	ID   int
	Name string
	Age  int
}

type UserDTO struct {
	Name string
	Age  int
}

func main() {
	user := User{ID: 1, Name: "Alice", Age: 25}
	var userDTO UserDTO

	// 复制数据
	copier.Copy(&userDTO, &user)

	fmt.Println(userDTO) // 输出: {Alice 25}
}

4.2 结构体切片拷贝

func main() {
	users := []User{
		{ID: 1, Name: "Alice", Age: 25},
		{ID: 2, Name: "Bob", Age: 30},
	}

	var userDTOs []UserDTO
	copier.Copy(&userDTOs, &users)

	fmt.Println(userDTOs) // 输出: [{Alice 25} {Bob 30}]
}

4.3 指针结构体拷贝

func main() {
	user := &User{ID: 1, Name: "Alice", Age: 25}
	var userDTO UserDTO

	copier.Copy(&userDTO, user)
	fmt.Println(userDTO) // 输出: {Alice 25}
}

4.4 处理不同字段类型

type UserExtended struct {
	ID        int
	Name      string
	Age       int
	IsActive  bool
	JoinDate  string
}

type UserSummary struct {
	FullName string `copier:"Name"`
	Active   bool   `copier:"IsActive"`
}

func main() {
	user := UserExtended{ID: 1, Name: "Alice", Age: 25, IsActive: true, JoinDate: "2023-01-01"}
	var summary UserSummary

	copier.Copy(&summary, &user)
	fmt.Println(summary) // 输出: {Alice true}
}

4.5 mapstruct 的拷贝

func main() {
	data := map[string]interface{}{
		"Name": "Charlie",
		"Age": 28,
	}

	var user UserDTO
	copier.Copy(&user, &data)

	fmt.Println(user) // 输出: {Charlie 28}
}

5. 结论

github.com/jinzhu/copier 提供了一种简洁高效的方法来在结构体、切片和 map 之间拷贝数据,减少手动字段映射的工作量,提升代码可读性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值