copier

package module
v0.3.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 17, 2023 License: MIT Imports: 8 Imported by: 0

README

Copier

I am a copier, I copy everything from one to another

test status

Features

  • Copy from field to field with same name
  • Copy from method to field with same name
  • Copy from field to method with same name
  • Copy from slice to slice
  • Copy from struct to slice
  • Copy from map to map
  • Enforce copying a field with a tag
  • Ignore a field with a tag
  • Deep Copy

Usage

package main

import (
	"fmt"
	"github.com/ekulabuhov/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}
}
Copy with Option
copier.CopyWithOption(&to, &from, copier.Option{IgnoreEmpty: true, DeepCopy: true})

Specifying default flags

var A struct {
	MappedField  string
	MissingField string
}

var B struct {
	MappedField string
}

err := copier.CopyWithOption(&B, &A, copier.Option{
	DefaultSourceFlags: copier.TagMust | copier.TagNoPanic,
})

// Outputs "field MissingField has must tag but was not copied"
fmt.Print(err)

Preserving fields on the merged-to structure

type C struct {
	D string
}

type D struct {
	C string
	D string
}

from := C{
	D: "2",
}

to := D{
	C: "3",
	D: "1",
}

err := copier.CopyWithOption(&to, &from, copier.Option{SkipFieldIfNotInFrom: true})

/* output will copy D and preserve C:
D{
	C: "3",
	D: "2",
}
*/

Contributing

You can help to make the project better, check out http://gorm.io/contribute.html for things you can do.

Author

jinzhu

License

Released under the MIT License.

Documentation

Index

Constants

View Source
const (
	// Denotes that a destination field must be copied to. If copying fails then a panic will ensue.
	TagMust uint8 = 1 << iota

	// Denotes that the program should not panic when the must flag is on and
	// value is not copied. The program will return an error instead.
	TagNoPanic

	// Won't apply default tags if value is a pointer
	TagSkipPtrs

	// Some default converter types for a nicer syntax
	String  string  = ""
	Bool    bool    = false
	Int     int     = 0
	Float32 float32 = 0
	Float64 float64 = 0
)

These flags define options for tag handling

Variables

View Source
var (
	ErrInvalidCopyDestination        = errors.New("copy destination must be non-nil and addressable")
	ErrInvalidCopyFrom               = errors.New("copy from must be non-nil and addressable")
	ErrMapKeyNotMatch                = errors.New("map's key type doesn't match")
	ErrNotSupported                  = errors.New("not supported")
	ErrFieldNameTagStartNotUpperCase = errors.New("copier field name tag must be start upper case")
)

Functions

func Copy

func Copy(toValue interface{}, fromValue interface{}) (err error)

Copy copy things

func CopyWithOption

func CopyWithOption(toValue interface{}, fromValue interface{}, opt Option) (err error)

CopyWithOption copy with option

Types

type FieldNameMapping added in v0.3.7

type FieldNameMapping struct {
	SrcType interface{}
	DstType interface{}
	Mapping map[string]string
}

type Option

type Option struct {
	// setting this value to true will ignore copying zero values of all the fields, including bools, as well as a
	// struct having all it's fields set to their zero values respectively (see IsZero() in reflect/value.go)
	IgnoreEmpty        bool
	CaseSensitive      bool
	DeepCopy           bool
	Converters         []TypeConverter
	DefaultSourceFlags uint8
	DefaultTargetFlags uint8
	// Custom field name mappings to copy values with different names in `fromValue` and `toValue` types.
	// Examples can be found in `copier_field_name_mapping_test.go`.
	FieldNameMapping []FieldNameMapping
	// If the field is not present on the origin, we won't overwrite it
	SkipFieldIfNotInFrom bool
	// contains filtered or unexported fields
}

Option sets copy options

type TypeConverter

type TypeConverter struct {
	SrcType interface{}
	DstType interface{}
	Fn      func(src interface{}) (dst interface{}, err error)
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL