Skip to content
鼓励作者:欢迎打赏犒劳

go对象拷贝

go
package main

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

// 源结构体
type User struct {
    ID        int       `json:"id"`
    Name      string    `json:"name"`
    Email     string    `json:"email"`
    CreatedAt time.Time `json:"created_at"`
    // 私有字段(小写开头)
    password  string
    // 嵌套结构
    Address   Address   `json:"address"`
}

// 目标结构体
type UserDTO struct {
    ID        int    `json:"id"`
    Name      string `json:"name"`
    Email     string `json:"email"`
    // 字段名称不同
    Created   string `json:"created"`
    // 嵌套结构
    Address   AddressDTO `json:"address"`
}

// 嵌套结构体 - 源
type Address struct {
    City    string `json:"city"`
    Country string `json:"country"`
    ZipCode string `json:"zip_code"`
}

// 嵌套结构体 - 目标
type AddressDTO struct {
    City    string `json:"city"`
    Country string `json:"country"`
    // 字段名称不同
    Zip      string `json:"zip"`
}

func main() {
    // 创建源对象
    user := User{
        ID:        1,
        Name:      "张三",
        Email:     "zhangsan@example.com",
        CreatedAt: time.Now(),
        password:  "secret",
        Address: Address{
            City:    "北京",
            Country: "中国",
            ZipCode: "100000",
        },
    }
    
    fmt.Println("源对象:")
    fmt.Printf("%+v\n", user)
    
    // 1. 基本拷贝
    var userDTO UserDTO
    err := copier.Copy(&userDTO, &user)
    if err != nil {
        panic(err)
    }
    
    fmt.Println("\n基本拷贝结果:")
    fmt.Printf("%+v\n", userDTO)
    
    // 2. 使用自定义转换器处理字段名称不同的情况
    copier.CopyWithOption(&userDTO, &user, copier.Option{
        IgnoreEmpty: false,
        DeepCopy:    false,
        Converters: []copier.TypeConverter{
            {
                SrcType: time.Time{},
                DstType: copier.String,
                Fn: func(src interface{}) (interface{}, error) {
                    s := src.(time.Time)
                    return s.Format("2006-01-02 15:04:05"), nil
                },
            },
            {
                SrcType: Address{},
                DstType: AddressDTO{},
                Fn: func(src interface{}) (interface{}, error) {
                    s := src.(Address)
                    return AddressDTO{
                        City:    s.City,
                        Country: s.Country,
                        Zip:     s.ZipCode,
                    }, nil
                },
            },
        },
    })
    
    fmt.Println("\n使用转换器后的拷贝结果:")
    fmt.Printf("%+v\n", userDTO)
    
    // 3. 切片拷贝示例
    users := []User{user, {
        ID:        2,
        Name:      "李四",
        Email:     "lisi@example.com",
        CreatedAt: time.Now().Add(-24 * time.Hour),
        password:  "secret2",
        Address: Address{
            City:    "上海",
            Country: "中国",
            ZipCode: "200000",
        },
    }}
    
    var userDTOs []UserDTO
    copier.CopyWithOption(&userDTOs, &users, copier.Option{
        Converters: []copier.TypeConverter{
            {
                SrcType: time.Time{},
                DstType: copier.String,
                Fn: func(src interface{}) (interface{}, error) {
                    s := src.(time.Time)
                    return s.Format("2006-01-02 15:04:05"), nil
                },
            },
            {
                SrcType: Address{},
                DstType: AddressDTO{},
                Fn: func(src interface{}) (interface{}, error) {
                    s := src.(Address)
                    return AddressDTO{
                        City:    s.City,
                        Country: s.Country,
                        Zip:     s.ZipCode,
                    }, nil
                },
            },
        },
    })
    
    fmt.Println("\n切片拷贝结果:")
    for i, dto := range userDTOs {
        fmt.Printf("%d: %+v\n", i+1, dto)
    }
}

结果

text
源对象:
{ID:1 Name:张三 Email:zhangsan@example.com CreatedAt:2023-07-15 10:30:45.123456 +0800 CST password:secret Address:{City:北京 Country:中国 ZipCode:100000}}

基本拷贝结果:
{ID:1 Name:张三 Email:zhangsan@example.com Created: Address:{City:北京 Country:中国 Zip:}}

使用转换器后的拷贝结果:
{ID:1 Name:张三 Email:zhangsan@example.com Created:2023-07-15 10:30:45 Address:{City:北京 Country:中国 Zip:100000}}

切片拷贝结果:
1: {ID:1 Name:张三 Email:zhangsan@example.com Created:2023-07-15 10:30:45 Address:{City:北京 Country:中国 Zip:100000}}
2: {ID:2 Name:李四 Email:lisi@example.com Created:2023-07-14 10:30:45 Address:{City:上海 Country:中国 Zip:200000}}

如有转载或 CV 的请标注本站原文地址