Top Related Projects
A Commander for modern Go CLI interactions
A Go library for implementing command-line interfaces.
CONTRIBUTIONS ONLY: A Go (golang) command line and flag parser
✨ #PTerm is a modern Go module to easily beautify console output. Featuring charts, progressbars, tables, trees, text input, select menus and much more 🚀 It's completely configurable and 100% cross-platform compatible.
Quick Overview
Copier is a Go library designed for efficient copying of values between different types. It provides a simple and flexible way to copy data from one struct to another, even when the structures have different field names or types. This library is particularly useful for mapping data between models, DTOs, and other data structures in Go applications.
Pros
- Supports copying between different types with minimal configuration
- Handles nested structures and slices efficiently
- Provides options for customizing the copying process
- Lightweight and easy to integrate into existing projects
Cons
- May not handle all complex scenarios without additional configuration
- Limited support for copying unexported fields
- Documentation could be more comprehensive
- Might introduce unexpected behavior if not used carefully
Code Examples
- Basic copying between structs:
type User struct {
Name string
Age int
}
type UserDTO struct {
FullName string
Age int
}
user := User{Name: "John Doe", Age: 30}
var userDTO UserDTO
copier.Copy(&userDTO, &user)
fmt.Printf("%+v\n", userDTO) // Output: {FullName:John Doe Age:30}
- Copying with field name mapping:
type Source struct {
Field1 string
Field2 int
}
type Destination struct {
CustomField1 string
CustomField2 int
}
source := Source{Field1: "Hello", Field2: 42}
var dest Destination
copier.CopyWithOption(&dest, &source, copier.Option{
FieldMapping: map[string]string{
"Field1": "CustomField1",
"Field2": "CustomField2",
},
})
fmt.Printf("%+v\n", dest) // Output: {CustomField1:Hello CustomField2:42}
- Copying slices:
type Item struct {
Name string
Value int
}
source := []Item{{Name: "Item1", Value: 10}, {Name: "Item2", Value: 20}}
var dest []Item
copier.Copy(&dest, &source)
fmt.Printf("%+v\n", dest) // Output: [{Name:Item1 Value:10} {Name:Item2 Value:20}]
Getting Started
To use Copier in your Go project, follow these steps:
-
Install the library:
go get github.com/jinzhu/copier
-
Import the library in your Go file:
import "github.com/jinzhu/copier"
-
Use the
Copy
orCopyWithOption
function to copy data between structs:var dest DestType copier.Copy(&dest, &source)
That's it! You can now start using Copier to efficiently copy data between different types in your Go application.
Competitor Comparisons
A Commander for modern Go CLI interactions
Pros of Cobra
- Robust CLI application framework with built-in command structure and flags
- Extensive documentation and large community support
- Generates boilerplate code and man pages automatically
Cons of Cobra
- Steeper learning curve for simple CLI tools
- More complex setup process compared to lightweight alternatives
- Potentially overkill for small projects or single-command applications
Code Comparison
Cobra:
var rootCmd = &cobra.Command{
Use: "app",
Short: "A brief description of your application",
Run: func(cmd *cobra.Command, args []string) {
// Your code here
},
}
Copier:
type Config struct {
Name string
}
err := copier.Copy(&dst, &src)
if err != nil {
// Handle error
}
Summary
Cobra is a powerful CLI framework for Go, offering robust features and extensive documentation. It excels in creating complex, multi-command applications but may be overwhelming for simpler projects. Copier, on the other hand, is a lightweight library focused on copying struct and field values, making it more suitable for specific data manipulation tasks rather than full CLI application development.
A Go library for implementing command-line interfaces.
Pros of cli
- More comprehensive CLI framework with built-in features like command parsing and help generation
- Better suited for complex command-line applications with multiple subcommands
- Actively maintained with regular updates and contributions
Cons of cli
- Steeper learning curve due to more complex API and features
- May be overkill for simple CLI tools or scripts
- Requires more boilerplate code to set up basic functionality
Code Comparison
cli:
c := cli.NewCLI("app", "1.0.0")
c.Args = os.Args[1:]
c.Commands = map[string]cli.CommandFactory{
"foo": fooCommandFactory,
}
copier:
copier.Copy(&dest, &src)
Summary
cli is a robust framework for building complex command-line applications in Go, offering features like command parsing and help generation. It's well-maintained but may have a steeper learning curve.
copier, on the other hand, is a simpler library focused on copying struct and field values. It's more lightweight and easier to use for basic object copying tasks but lacks CLI-specific features.
Choose cli for full-fledged CLI applications and copier for straightforward struct copying operations.
CONTRIBUTIONS ONLY: A Go (golang) command line and flag parser
Pros of Kingpin
- Focused on command-line flag parsing and application structure
- Provides a more intuitive and expressive API for defining CLI commands and flags
- Offers built-in help generation and version flag support
Cons of Kingpin
- Limited to CLI application development, unlike Copier's broader file templating capabilities
- May have a steeper learning curve for simple flag parsing tasks
- Less flexibility for general-purpose file manipulation and generation
Code Comparison
Kingpin:
var (
verbose = kingpin.Flag("verbose", "Verbose mode.").Short('v').Bool()
name = kingpin.Arg("name", "Name of user.").Required().String()
)
func main() {
kingpin.Parse()
fmt.Printf("%v, %s\n", *verbose, *name)
}
Copier:
from copier import copy
copy(
"template",
"destination",
data={"name": "John Doe", "age": 30},
exclude=["*.pyc", "__pycache__"],
)
Summary
Kingpin is a Go library specifically designed for building command-line applications with a focus on flag parsing and application structure. It offers a more intuitive API for defining CLI commands and flags, along with built-in help generation. However, it's limited to CLI development and may have a steeper learning curve for simple tasks.
Copier, on the other hand, is a Python library for file templating and project scaffolding. It provides more flexibility for general-purpose file manipulation and generation but lacks the specific CLI-focused features of Kingpin.
✨ #PTerm is a modern Go module to easily beautify console output. Featuring charts, progressbars, tables, trees, text input, select menus and much more 🚀 It's completely configurable and 100% cross-platform compatible.
Pros of pterm
- Focused on terminal output styling and formatting
- Extensive set of pre-built components for terminal UI
- Active development with frequent updates
Cons of pterm
- Limited to terminal output, not a general-purpose file manipulation tool
- Steeper learning curve for complex terminal UI components
- Larger dependency footprint
Code Comparison
pterm example:
pterm.DefaultHeader.WithFullWidth().Println("Hello, World!")
pterm.Info.Println("This is a simple example")
pterm.Println("Goodbye!")
copier example:
err := copier.Copy(&dest, src)
if err != nil {
log.Fatal(err)
}
Key Differences
pterm is a Go library for creating rich terminal output with various styling options and UI components. It's ideal for building interactive CLI applications with visually appealing interfaces.
copier, on the other hand, is a Go library for deep copying structs and slices. It's useful for data manipulation and object cloning tasks, particularly when working with complex data structures.
While both are Go libraries, they serve entirely different purposes. pterm enhances terminal output, while copier focuses on data copying and manipulation. The choice between them depends on whether you need to create rich terminal UIs or perform deep copying of data structures in your Go projects.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Copier
I am a copier, I copy everything from one to another
Key Features
- Field-to-field and method-to-field copying based on matching names
- Support for copying data:
- From slice to slice
- From struct to slice
- From map to map
- Field manipulation through tags:
- Enforce field copying with
copier:"must"
- Override fields even when
IgnoreEmpty
is set withcopier:"override"
- Exclude fields from being copied with
copier:"-"
- Enforce field copying with
Getting Started
Installation
To start using Copier, install Go and run go get:
go get -u github.com/jinzhu/copier
Basic
Import Copier into your application to access its copying capabilities
import "github.com/jinzhu/copier"
Basic Copying
type User struct {
Name string
Role string
Age int32
}
func (user *User) DoubleAge() int32 {
return 2 * user.Age
}
type Employee struct {
Name string
Age int32
DoubleAge int32
SuperRole string
}
func (employee *Employee) Role(role string) {
employee.SuperRole = "Super " + role
}
func main() {
user := User{Name: "Jinzhu", Age: 18, Role: "Admin"}
employee := Employee{}
copier.Copy(&employee, &user)
fmt.Printf("%#v\n", employee)
// Output: Employee{Name:"Jinzhu", Age:18, DoubleAge:36, SuperRole:"Super Admin"}
}
Tag Usage Examples
copier:"-"
- Ignoring Fields
Fields tagged with copier:"-"
are explicitly ignored by Copier during the copying process.
type Source struct {
Name string
Secret string // We do not want this to be copied.
}
type Target struct {
Name string
Secret string `copier:"-"`
}
func main() {
source := Source{Name: "John", Secret: "so_secret"}
target := Target{}
copier.Copy(&target, &source)
fmt.Printf("Name: %s, Secret: '%s'\n", target.Name, target.Secret)
// Output: Name: John, Secret: ''
}
copier:"must"
- Enforcing Field Copy
The copier:"must"
tag forces a field to be copied, resulting in a panic or an error if the field cannot be copied.
type MandatorySource struct {
Identification int
}
type MandatoryTarget struct {
ID int `copier:"must"` // This field must be copied, or it will panic/error.
}
func main() {
source := MandatorySource{}
target := MandatoryTarget{ID: 10}
// This will result in a panic or an error since ID is a must field but is empty in source.
if err := copier.Copy(&target, &source); err != nil {
log.Fatal(err)
}
}
copier:"must,nopanic"
- Enforcing Field Copy Without Panic
Similar to copier:"must"
, but Copier returns an error instead of panicking if the field is not copied.
type SafeSource struct {
ID string
}
type SafeTarget struct {
Code string `copier:"must,nopanic"` // Enforce copying without panic.
}
func main() {
source := SafeSource{}
target := SafeTarget{Code: "200"}
if err := copier.Copy(&target, &source); err != nil {
log.Fatalln("Error:", err)
}
// This will not panic, but will return an error due to missing mandatory field.
}
copier:"override"
- Overriding Fields with IgnoreEmpty
Fields tagged with copier:"override"
are copied even if IgnoreEmpty is set to true in Copier options and works for nil values.
type SourceWithNil struct {
Details *string
}
type TargetOverride struct {
Details *string `copier:"override"` // Even if source is nil, copy it.
}
func main() {
details := "Important details"
source := SourceWithNil{Details: nil}
target := TargetOverride{Details: &details}
copier.CopyWithOption(&target, &source, copier.Option{IgnoreEmpty: true})
if target.Details == nil {
fmt.Println("Details field was overridden to nil.")
}
}
Specifying Custom Field Names
Use field tags to specify a custom field name when the source and destination field names do not match.
type SourceEmployee struct {
Identifier int64
}
type TargetWorker struct {
ID int64 `copier:"Identifier"` // Map Identifier from SourceEmployee to ID in TargetWorker
}
func main() {
source := SourceEmployee{Identifier: 1001}
target := TargetWorker{}
copier.Copy(&target, &source)
fmt.Printf("Worker ID: %d\n", target.ID)
// Output: Worker ID: 1001
}
Other examples
Copy from Method to Field with Same Name
Illustrates copying from a method to a field and vice versa.
// Assuming User and Employee structs defined earlier with method and field respectively.
func main() {
user := User{Name: "Jinzhu", Age: 18}
employee := Employee{}
copier.Copy(&employee, &user)
fmt.Printf("DoubleAge: %d\n", employee.DoubleAge)
// Output: DoubleAge: 36, demonstrating method to field copying.
}
Copy Struct to Slice
func main() {
user := User{Name: "Jinzhu", Age: 18, Role: "Admin"}
var employees []Employee
copier.Copy(&employees, &user)
fmt.Printf("%#v\n", employees)
// Output: []Employee{{Name: "Jinzhu", Age: 18, DoubleAge: 36, SuperRole: "Super Admin"}}
}
Copy Slice to Slice
func main() {
users := []User{{Name: "Jinzhu", Age: 18, Role: "Admin"}, {Name: "jinzhu 2", Age: 30, Role: "Dev"}}
var employees []Employee
copier.Copy(&employees, &users)
fmt.Printf("%#v\n", employees)
// Output: []Employee{{Name: "Jinzhu", Age: 18, DoubleAge: 36, SuperRole: "Super Admin"}, {Name: "jinzhu 2", Age: 30, DoubleAge: 60, SuperRole: "Super Dev"}}
}
Copy Map to Map
func main() {
map1 := map[int]int{3: 6, 4: 8}
map2 := map[int32]int8{}
copier.Copy(&map2, map1)
fmt.Printf("%#v\n", map2)
// Output: map[int32]int8{3:6, 4:8}
}
Complex Data Copying: Nested Structures with Slices
This example demonstrates how Copier can be used to copy data involving complex, nested structures, including slices of structs, to showcase its ability to handle intricate data copying scenarios.
package main
import (
"fmt"
"github.com/jinzhu/copier"
)
type Address struct {
City string
Country string
}
type Contact struct {
Email string
Phones []string
}
type Employee struct {
Name string
Age int32
Addresses []Address
Contact *Contact
}
type Manager struct {
Name string `copier:"must"`
Age int32 `copier:"must,nopanic"`
ManagedCities []string
Contact *Contact `copier:"override"`
SecondaryEmails []string
}
func main() {
employee := Employee{
Name: "John Doe",
Age: 30,
Addresses: []Address{
{City: "New York", Country: "USA"},
{City: "San Francisco", Country: "USA"},
},
Contact: nil,
}
manager := Manager{
ManagedCities: []string{"Los Angeles", "Boston"},
Contact: &Contact{
Email: "john.doe@example.com",
Phones: []string{"123-456-7890", "098-765-4321"},
}, // since override is set this should be overridden with nil
SecondaryEmails: []string{"secondary@example.com"},
}
copier.CopyWithOption(&manager, &employee, copier.Option{IgnoreEmpty: true, DeepCopy: true})
fmt.Printf("Manager: %#v\n", manager)
// Output: Manager struct showcasing copied fields from Employee,
// including overridden and deeply copied nested slices.
}
Available tags
Tag | Description |
---|---|
copier:"-" | Explicitly ignores the field during copying. |
copier:"must" | Forces the field to be copied; Copier will panic or return an error if the field is not copied. |
copier:"nopanic" | Copier will return an error instead of panicking. |
copier:"override" | Forces the field to be copied even if IgnoreEmpty is set. Useful for overriding existing values with empty ones |
FieldName | Specifies a custom field name for copying when field names do not match between structs. |
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.
Top Related Projects
A Commander for modern Go CLI interactions
A Go library for implementing command-line interfaces.
CONTRIBUTIONS ONLY: A Go (golang) command line and flag parser
✨ #PTerm is a modern Go module to easily beautify console output. Featuring charts, progressbars, tables, trees, text input, select menus and much more 🚀 It's completely configurable and 100% cross-platform compatible.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot