copier
Reflection-based Go library for copying values between structs, slices, and maps with tag-driven field control.
Repository Health
Technical Analysis
Copier is a small, dependency-free Go library that copies data between structs, slices, and maps using reflection, matching fields and methods by name rather than requiring manual field-by-field assignment. It handles nested structs, embedded/anonymous fields, pointer dereferencing, and type conversion automatically, and integrates with database/sql’s Scanner and Valuer interfaces for working with nullable SQL types.
Struct tags (copier:"must", copier:"-", copier:"override", custom field names) and CopyWithOption settings (IgnoreEmpty, DeepCopy, CaseSensitive, custom converters, field name mappings) give fine-grained control over how individual fields are copied, making it a common choice for mapping between DTOs, ORM models, and API request/response types without writing boilerplate conversion code.
What You Get
- Field-to-field and method-to-field copying based on matching names
- Support for slice-to-slice, struct-to-slice, and map-to-map copying
- Struct tags for enforcing (
must), ignoring (-), and overriding fields - CopyWithOption controls: IgnoreEmpty, DeepCopy, CaseSensitive matching
- Custom type converters and field name mappings for mismatched schemas
- Built-in support for database/sql Scanner and Valuer interfaces
Common Use Cases
- Mapping database ORM models to API response DTOs
- Converting between versioned API request/response structs
- Populating view models from domain models in web handlers
- Cloning structs with select fields overridden via IgnoreEmpty/override tags
- Bulk-copying slices of structs, e.g. entity lists to view-model lists
Under The Hood
Architecture
The package is a flat, single-file implementation (copier.go plus errors.go) built around one recursive copier() function that inspects reflect.Value/reflect.Type pairs and dispatches by type kind (slice, map, struct, primitive), delegating scalar/pointer coercion, sql.Scanner/Valuer bridging, and TypeConverter lookup to a shared set() helper. Struct field introspection is memoized in a package-level deepFieldsMap guarded by sync.RWMutex to avoid repeated reflection walks on the same type. There’s no layering in the OOP sense — Copy/CopyWithOption are the only two public entry points, and everything else (copier, set, getFlags, parseTags, fieldByName, deepFields) is an unexported helper called recursively from that core function, so changes to the central dispatch logic ripple through every type-kind branch (slice, map, struct, pointer) at once.
Tech Stack
A Go 1.13 module with zero external dependencies — only the standard library (reflect, database/sql, database/sql/driver, fmt, strings, sync, unicode). There’s no build tooling beyond go build/go test; CI (.github/workflows/tests.yml) runs go test across a matrix of Go 1.17 through 1.22 on Ubuntu and macOS. It ships as a plain importable package with no CLI, binary, ORM, or web framework involved — a pure reflection utility meant to be pulled into other Go codebases.
Code Quality
The repo has an extensive test suite: a large primary copier_test.go alongside focused files for struct tags, type converters, benchmarks, case-insensitive matching, field-name mapping, and specific regression cases tied to GitHub issues — all using the standard library testing package with no external assertion library. Error handling mixes explicit error return values (e.g. ErrInvalidCopyDestination, ErrMapKeyNotMatch) with panic() for must-tagged fields unless nopanic is also set, which is a deliberate but sharp-edged design choice. Naming follows idiomatic Go conventions, and no generics are used despite Go 1.18+ appearing in the CI matrix — the library relies entirely on interface{} and reflection. No linter configuration or coverage reporting is visible in the repo.
API Design
The public surface is intentionally minimal: two functions, Copy and CopyWithOption, cover nearly every use case, with a single Option struct (IgnoreEmpty, DeepCopy, CaseSensitive, Converters, FieldNameMapping, Must, NoPanic) providing progressive complexity rather than a sprawling function surface. Getting started requires no boilerplate — copier.Copy(&dst, &src) is a complete call — and the README documents every struct tag and option with runnable examples. Naming across tags (copier:"must", copier:"-", copier:"override") is consistent, though the default panic-on-must-tag behavior is a notable developer-experience sharp edge that requires opting into nopanic to get error-based handling instead of a runtime panic.
Used by 5 apps in this directory
1Panel
Devops · Hosting Control Panel · Monitoring
The only open-source VPS control panel with native AI agent runtime — deploy websites, Docker stacks, and local LLMs from one web interface.
Apache Answer
Community
Open-source Q&A platform for communities, help centers, and knowledge bases with AI assistant and plugin extensibility
Nightingale
Monitoring
Open-source alerting engine that connects to any time-series or log data source and routes alarms to 20+ notification channels with AI-assisted triage.
Plandex
AI Code Assistants
An open-source, terminal-based AI coding agent built for large tasks and real codebases — with its own version control for plans, a 2M-token effective context window, and self-hosted or cloud deployment.
Vikunja
Project Management
Self-hosted task management with natural-language quick-add, multiple views, and a fully documented REST API — your tasks, your infrastructure, zero lock-in.