copier库golang中的dto库

应用场景:

copier库允许在go中使用dto,相等于.net automapper

常规用法:更多请移步githubjinzhu/copier: Copier for golang, copy value from struct to struct and more (github.com)

package main

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

type User struct {
	Name        string
	Role        string
	Age         int32
	EmployeeCode int64 `copier:"EmployeeNum"` // specify field name

	// Explicitly ignored in the destination struct.
	Salary   int
}

func (user *User) DoubleAge() int32 {
	return 2 * user.Age
}

// Tags in the destination Struct provide instructions to copier.Copy to ignore
// or enforce copying and to panic or return an error if a field was not copied.
type Employee struct {
	// Tell copier.Copy to panic if this field is not copied.
	Name      string `copier:"must"`

	// Tell copier.Copy to return an error if this field is not copied.
	Age       int32  `copier:"must,nopanic"`

	// Tell copier.Copy to explicitly ignore copying this field.
	Salary    int    `copier:"-"`

	DoubleAge int32
	EmployeeId int64 `copier:"EmployeeNum"` // specify field name
	SuperRole string
}

func (employee *Employee) Role(role string) {
	employee.SuperRole = "Super " + role
}

func main() {
	var (
		user      = User{Name: "Jinzhu", Age: 18, Role: "Admin", Salary: 200000}
		users     = []User{{Name: "Jinzhu", Age: 18, Role: "Admin", Salary: 100000}, {Name: "jinzhu 2", Age: 30, Role: "Dev", Salary: 60000}}
		employee  = Employee{Salary: 150000}
		employees = []Employee{}
	)

	copier.Copy(&employee, &user)

	fmt.Printf("%#v \n", employee)
	// Employee{
	//    Name: "Jinzhu",           // Copy from field
	//    Age: 18,                  // Copy from field
	//    Salary:150000,            // Copying explicitly ignored
	//    DoubleAge: 36,            // Copy from method
	//    EmployeeId: 0,            // Ignored
	//    SuperRole: "Super Admin", // Copy to method
	// }

	// Copy struct to slice
	copier.Copy(&employees, &user)

	fmt.Printf("%#v \n", employees)
	// []Employee{
	//   {Name: "Jinzhu", Age: 18, Salary:0, DoubleAge: 36, EmployeeId: 0, SuperRole: "Super Admin"}
	// }

	// Copy slice to slice
	employees = []Employee{}
	copier.Copy(&employees, &users)

	fmt.Printf("%#v \n", employees)
	// []Employee{
	//   {Name: "Jinzhu", Age: 18, Salary:0, DoubleAge: 36, EmployeeId: 0, SuperRole: "Super Admin"},
	//   {Name: "jinzhu 2", Age: 30, Salary:0, DoubleAge: 60, EmployeeId: 0, SuperRole: "Super Dev"},
	// }

 	// Copy map to map
	map1 := map[int]int{3: 6, 4: 8}
	map2 := map[int32]int8{}
	copier.Copy(&map2, map1)

	fmt.Printf("%#v \n", map2)
	// map[int32]int8{3:6, 4:8}
}

画风突变情况:

想把用户信息中的用户角色列表转换成[]int32 切片返回给前端,最开始用上面的方法是不行的,没法直接把[]UserRole转换为[]int32,好在打工人不气馁,不妥协,通过不停的试探终于解决了。。。


代码如下

// 用户信息struct
type Users struct {
	Account   string     `json:"account" gorm:"unique;size:50;comment:账号"`
	Password  string     `json:"-" gorm:"comment:密码" copier:"-"`
	Slat      string     `json:"-" gorm:"comment:加密盐" copier:"-"`
	Name      string     `json:"name" gorm:"size:50;comment:姓名"`
	Age       uint8      `json:"age,omitempty" gorm:"size:4;comment:年龄"`
	Gender    uint8      `json:"gender,omitempty" gorm:"size:1;comment:性别"`
	Phone     string     `json:"phone,omitempty" gorm:"size:11;comment:电话"`
	Email     string     `json:"email,omitempty" gorm:"size:100;comment:邮箱"`
	IsActive  bool       `json:"isActive,omitempty" gorm:"size:1;comment:是否激活"`
	UserRoles []UserRole `json:"roles,omitempty" gorm:"foreignKey:UserID"`
	Entity
}

// 需要映射的dto
type UserDto struct {
	Account    string    `json:"account"`
	Name       string    `json:"name"`
	Age        uint8     `json:"age,omitempty"`
	Gender     uint8     `json:"gender,omitempty"`
	Phone      string    `json:"phone,omitempty"`
	Email      string    `json:"email,omitempty"`
	IsActive   bool      `json:"isActive"`
	IsDelete   bool      `json:"isDelete"`
	CreateBy   string    `json:"createBy,omitempty"`
	CreateTime time.Time `json:"createTime,omitempty"`
	UserRoles  []int32   `json:"roles,omitempty"`
}

利用copier 的CopyWithOption 方法自定义映射规则

// 自定义 TypeConverter, Users 转成Dto 
var UserToDto = []copier.TypeConverter{
	{
        // 源类型
		SrcType: []domain.UserRole{},
        // 映射类型
		DstType: []int32{},
        // 转换函数
		Fn: func(src interface{}) (interface{}, error) {
            // 类型断言, 把src转换成domain.UserRole
			s, ok := src.([]domain.UserRole)
			if !ok {
				return nil, errors.New("src type not matching")
			}
            // 创建RoleID的切片
			r := make([]int32, 0)
			for _, v := range s {
				r = append(r, v.RoleID)
			}
			return r, nil
		},
	},
    {   // Dto []int32 转 []domain.Users
		SrcType: []int32{},
		DstType: []domain.UserRole{},
		Fn: func(src interface{}) (interface{}, error) {
			s, ok := src.([]int32)
			if !ok {
				return nil, errors.New("src type not matching")
			}
			r := make([]domain.UserRole, 0)
			for _, v := range s {
				r = append(r, domain.UserRole{RoleID: v})
			}
			return r, nil
		},
	},
}

// 转换的时候,写上以下代码即可,就是这么的简单丝滑

err = copier.CopyWithOption(&udto, user, copier.Option{IgnoreEmpty: true, DeepCopy: true, Converters: contracts.UserToDto})

 最终结果:

 

欢迎大佬指点,讨论。。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值