deepcopy
Deep-copies arbitrary Go values via reflection, recursing through structs, slices, maps, and pointers.
Repository Health
Technical Analysis
deepcopy is a small, single-purpose Go library that produces a true deep copy of any value passed to it. Unlike a plain assignment or shallow copy, which only duplicates pointers, deepcopy walks the value with reflect and rebuilds structs, slices, maps, and pointer chains field by field so the copy shares no underlying memory with the original.
The package exposes one core entry point, Copy(src interface{}) interface{}, plus a deepcopy.Interface hook so a type can implement its own DeepCopy() interface{} method when the default reflection-based traversal isn’t appropriate. Unexported struct fields are intentionally skipped rather than copied, since they can’t be set via reflection from outside the package anyway.
What You Get
- A single
Copy()function that deep-copies any interface{} value using reflection - Recursive handling of pointers, interfaces, structs, slices, and maps
- An
Interface/DeepCopy()override hook for types that need custom copy logic - Special-cased handling for
time.Timeso time values copy correctly instead of being walked field by field - An
Iface()alias kept for backwards compatibility with earlier API versions
Common Use Cases
- Snapshotting configuration or state structs before mutating them, so the original can be restored or compared later
- Cloning request/response structs in test fixtures so tests don’t share mutable state
- Copying cached data structures before handing them to a caller that might mutate them
- Duplicating nested map/slice-based data (e.g. parsed JSON as
map[string]interface{}) without aliasing
Under The Hood
Architecture
The entire package lives in one file, deepcopy.go, exposing a single public entry point, Copy(src interface{}) interface{}, that delegates to an unexported recursive helper, copyRecursive(original, cpy reflect.Value). There is no layering to speak of: the exported API is a thin wrapper, and all the real logic is a single type-switch over reflect.Kind (Ptr, Interface, Struct, Slice, Map, and a default case) that recurses into itself for nested values. The one architectural extension point is the Interface/DeepCopy() hook, checked first in copyRecursive via a type assertion, letting a caller’s type override the reflection-based traversal entirely. Because everything funnels through this one function, changing how any single kind is copied is a localized, low-risk edit, but there is no separation between traversal, allocation, and copy-semantics concerns.
Tech Stack
deepcopy has zero external dependencies — it imports only the standard library’s reflect and time packages. There is no go.mod in the repository, meaning it predates (or has never adopted) Go modules and is consumed as a GOPATH-style import path (github.com/mohae/deepcopy), which still works fine under Go modules via go get with an inferred version. Continuous integration is configured via a legacy .travis.yml targeting older Go toolchains; there is no modern CI (GitHub Actions) configuration in the repo.
Code Quality
The library ships with an unusually large test file relative to the implementation (deepcopy_test.go is roughly 9x the size of deepcopy.go), covering strings, bools, bytes, ints, uints, structs, slices, maps, pointers, interfaces, and time.Time values. Tests verify deep-copy correctness by comparing reflect.SliceHeader/pointer data addresses via unsafe, confirming that copies don’t alias the original’s backing memory rather than just checking equal values. That said, the tests are written as one long function per type category using goto labels to fall through between sections rather than table-driven subtests (t.Run), which was a common style before Go’s subtest support matured. Error handling is minimal by design — the package has no error return path at all, and unsupported/edge-case kinds silently fall through to the default cpy.Set(original) case. No linter or formatter configuration is present in the repo.
What Makes It Unique
The reflection-based deep-copy pattern itself is a well-established one in the Go ecosystem, and this package doesn’t add anything beyond it — no cycle detection for circular references, no struct-tag-driven field exclusion, and no benchmarked performance comparisons against alternatives. Its value is in being an early, focused, dependency-free implementation of the pattern with unusually thorough correctness tests for the specific case of pointer/slice/map memory independence, along with the DeepCopy() override hook so higher-level types can special-case their own copy behavior when reflection alone isn’t sufficient.
Used by 3 apps in this directory
Authelia
Security · Authentication
OpenID Certified SSO and MFA portal for securing self-hosted web applications behind reverse proxies.
opencloud
File Storage
Open source file management and collaboration platform that keeps your data under your control, no database required.
Ory Kratos
Authentication
API-first identity and user management that handles login, registration, MFA, and recovery so your application never has to.