{"id":27890933,"url":"https://github.com/tiendc/go-deepcopy","last_synced_at":"2026-04-09T04:32:49.237Z","repository":{"id":180483557,"uuid":"662289420","full_name":"tiendc/go-deepcopy","owner":"tiendc","description":"Fast deep-copy library for Go","archived":false,"fork":false,"pushed_at":"2025-09-21T13:09:05.000Z","size":137,"stargazers_count":107,"open_issues_count":0,"forks_count":5,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-09-21T13:27:12.233Z","etag":null,"topics":["conversion","copier","copy","deep-copier","deep-copy","deepcopy","go","golang","reflection","transformation"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tiendc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-07-04T19:39:32.000Z","updated_at":"2025-09-21T13:07:42.000Z","dependencies_parsed_at":null,"dependency_job_id":"feb54bad-469a-45bd-92ad-4d98ba655a1b","html_url":"https://github.com/tiendc/go-deepcopy","commit_stats":null,"previous_names":["tiendc/go-deepcopy"],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/tiendc/go-deepcopy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tiendc%2Fgo-deepcopy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tiendc%2Fgo-deepcopy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tiendc%2Fgo-deepcopy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tiendc%2Fgo-deepcopy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tiendc","download_url":"https://codeload.github.com/tiendc/go-deepcopy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tiendc%2Fgo-deepcopy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31586404,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T14:31:17.711Z","status":"online","status_checked_at":"2026-04-09T02:00:06.848Z","response_time":112,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["conversion","copier","copy","deep-copier","deep-copy","deepcopy","go","golang","reflection","transformation"],"created_at":"2025-05-05T11:02:03.109Z","updated_at":"2026-04-09T04:32:49.223Z","avatar_url":"https://github.com/tiendc.png","language":"Go","readme":"[![Go Version][gover-img]][gover] [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] [![GoReport][rpt-img]][rpt]\n\n# Fast deep-copy library for Go\n\n## Functionalities\n\n- True deep copy\n- Very fast (see [benchmarks](#benchmarks) section)\n- Ability to copy almost all Go types (number, string, bool, function, slice, map, struct)\n- Ability to copy data between convertible types (for example: copy from `int` to `float`)\n- Ability to copy between `pointers` and `values` (for example: copy from `*int` to `int`)\n- Ability to copy values via copying methods of destination types\n- Ability to copy inherited fields from embedded structs\n- Ability to set a destination struct field as `nil` if it is `zero`\n- Ability to copy unexported struct fields\n- Ability to copy with extra configuration settings\n\n## Installation\n\n```shell\ngo get github.com/tiendc/go-deepcopy\n```\n\n## Usage\n\n- [First example](#first-example)\n- [Copy between struct fields with different names](#copy-between-struct-fields-with-different-names)\n- [Skip copying struct fields](#skip-copying-struct-fields)\n- [Require copying for struct fields](#require-copying-for-struct-fields)\n- [Copy struct fields via struct methods](#copy-struct-fields-via-struct-methods)\n- [Copy inherited fields from embedded structs](#copy-inherited-fields-from-embedded-structs)\n- [Set destination struct fields as `nil` on `zero`](#set-destination-struct-fields-as-nil-on-zero)\n- [PostCopy event method for structs](#postcopy-event-method-for-structs)\n- [Copy between structs and maps](#copy-between-structs-and-maps)\n- [Configure extra copying behaviors](#configure-extra-copying-behaviors)\n\n### First example\n\n  [Playground](https://go.dev/play/p/CrP_rZlkNzm)\n\n```go\n    type SS struct {\n        B bool\n    }\n    type S struct {\n        I  int\n        U  uint\n        St string\n        V  SS\n    }\n    type DD struct {\n        B bool\n    }\n    type D struct {\n        I int\n        U uint\n        X string\n        V DD\n    }\n    src := []S{{I: 1, U: 2, St: \"3\", V: SS{B: true}}, {I: 11, U: 22, St: \"33\", V: SS{B: false}}}\n    var dst []D\n    _ = deepcopy.Copy(\u0026dst, \u0026src) // NOTE: it is recommended that you always pass address of `src` to the function\n                                  // when copy structs having unexported fields such as `time.Time`.\n    for _, d := range dst {\n        fmt.Printf(\"%+v\\n\", d)\n    }\n\n    // Output:\n    // {I:1 U:2 X: V:{B:true}}\n    // {I:11 U:22 X: V:{B:false}}\n```\n\n### Copy between struct fields with different names\n\n  [Playground](https://go.dev/play/p/WchsGRns0O-)\n\n```go\n    type S struct {\n        X  int    `copy:\"Key\"` // 'Key' is used to match the fields\n        U  uint\n        St string\n    }\n    type D struct {\n        Y int     `copy:\"Key\"`\n        U uint\n    }\n    src := []S{{X: 1, U: 2, St: \"3\"}, {X: 11, U: 22, St: \"33\"}}\n    var dst []D\n    _ = deepcopy.Copy(\u0026dst, \u0026src)\n\n    for _, d := range dst {\n        fmt.Printf(\"%+v\\n\", d)\n    }\n\n    // Output:\n    // {Y:1 U:2}\n    // {Y:11 U:22}\n```\n\n### Skip copying struct fields\n\n- By default, matching fields will be copied. If you don't want to copy a field, use tag value `-`.\n\n  [Playground](https://go.dev/play/p/8KPe1Susjp1)\n\n```go\n    // S and D both have `I` field, but we don't want to copy it\n    // Tag `-` can be used in both struct definitions or just in one\n    type S struct {\n        I  int\n        U  uint\n        St string\n    }\n    type D struct {\n        I int `copy:\"-\"`\n        U uint\n    }\n    src := []S{{I: 1, U: 2, St: \"3\"}, {I: 11, U: 22, St: \"33\"}}\n    var dst []D\n    _ = deepcopy.Copy(\u0026dst, \u0026src)\n\n    for _, d := range dst {\n        fmt.Printf(\"%+v\\n\", d)\n    }\n\n    // Output:\n    // {I:0 U:2}\n    // {I:0 U:22}\n```\n\n### Require copying for struct fields\n\n  [Playground](https://go.dev/play/p/yDlLsv1wBnf)\n\n```go\n    type S struct {\n        U  uint\n        St string\n    }\n    type D struct {\n        I int `copy:\",required\"`\n        U uint\n    }\n    src := []S{{U: 2, St: \"3\"}, {U: 22, St: \"33\"}}\n    var dst []D\n    err := deepcopy.Copy(\u0026dst, \u0026src)\n    if err != nil {\n        fmt.Println(\"error:\", err)\n    }\n\n    // Output:\n    // error: ErrFieldRequireCopying: struct field 'main.D[I]' requires copying\n```\n\n### Copy struct fields via struct methods\n\n- **Note**: If a copying method is defined within a struct, it will have higher priority than matching fields.\n\n  [Playground 1](https://go.dev/play/p/rCawGa5AZh3) /\n  [Playground 2](https://go.dev/play/p/vDOhHXyUoyD)\n\n```go\ntype S struct {\n    X  int\n    U  uint\n    St string\n}\n\ntype D struct {\n    x string\n    U uint\n}\n\n// Copy method should be in form of `Copy\u003csource-field\u003e` (or key) and return `error` type\nfunc (d *D) CopyX(i int) error {\n    d.x = fmt.Sprintf(\"%d\", i)\n    return nil\n}\n```\n```go\n    src := []S{{X: 1, U: 2, St: \"3\"}, {X: 11, U: 22, St: \"33\"}}\n    var dst []D\n    _ = deepcopy.Copy(\u0026dst, \u0026src)\n\n    for _, d := range dst {\n        fmt.Printf(\"%+v\\n\", d)\n    }\n\n    // Output:\n    // {x:1 U:2}\n    // {x:11 U:22}\n```\n\n### Copy inherited fields from embedded structs\n\n- This is default behaviour from v1, for lower versions, you can use custom copying function\nto achieve the same result.\n\n  [Playground 1](https://go.dev/play/p/Zjj12AMRYXt) /\n  [Playground 2](https://go.dev/play/p/cJGLqpPVHXI)\n\n```go\n    type SBase struct {\n        St string\n    }\n    // Source struct has an embedded one\n    type S struct {\n        SBase\n        I int\n    }\n    // but destination struct doesn't\n    type D struct {\n        I  int\n        St string\n    }\n\n    src := []S{{I: 1, SBase: SBase{\"abc\"}}, {I: 11, SBase: SBase{\"xyz\"}}}\n    var dst []D\n    _ = deepcopy.Copy(\u0026dst, \u0026src)\n\n    for _, d := range dst {\n        fmt.Printf(\"%+v\\n\", d)\n    }\n\n    // Output:\n    // {I:1 St:abc}\n    // {I:11 St:xyz}\n```\n\n### Set destination struct fields as `nil` on `zero`\n\n- This is a new feature from v1.5.0. This applies to destination fields of type `pointer`, `interface`,\n`slice`, and `map`. When their values are zero after copying, they will be set as `nil`. This is very\nconvenient when you don't want to send something like a date of `0001-01-01` to client, you want to send\n`null` instead.\n\n[Playground 1](https://go.dev/play/p/GO6VExVOLei) /\n[Playground 2](https://go.dev/play/p/u0zMHx9UWjA) /\n[Playground 3](https://go.dev/play/p/ZpA8DkQ9-7f)\n\n```go\n    // Source struct has a time.Time field\n    type S struct {\n        I    int\n        Time time.Time\n    }\n    // Destination field must be a nullable value such as `*time.Time` or `interface{}`\n    type D struct {\n        I    int\n        Time *time.Time `copy:\",nilonzero\"` // make sure to use this tag\n    }\n\n    src := []S{{I: 1, Time: time.Time{}}, {I: 11, Time: time.Now()}}\n    var dst []D\n    _ = deepcopy.Copy(\u0026dst, \u0026src)\n\n    for _, d := range dst {\n        fmt.Printf(\"%+v\\n\", d)\n    }\n\n    // Output:\n    // {I:1 Time:\u003cnil\u003e} (source is a zero time value, destination becomes `nil`)\n    // {I:11 Time:2025-02-08 12:31:11...} (source is not zero, so be the destination)\n```\n\n### `PostCopy` event method for structs\n\n- This is a new feature from v1.5.0. If a destination struct has PostCopy() method, it will be called after copying.\n\n  [Playground](https://go.dev/play/p/fGhGZumaRUD)\n\n```go\n    type S struct {\n        I  int\n        St string\n    }\n    type D struct {\n        I  int\n        St string\n    }\n    // PostCopy must be defined on struct pointer, not value\n    func (d *D) PostCopy(src any) error {\n        d.I *= 2\n        d.St += d.St\n        return nil\n    }\n\n    src := []S{{I: 1, St: \"a\"}, {I: 11, St: \"aa\"}}\n    var dst []D\n    _ = deepcopy.Copy(\u0026dst, \u0026src)\n\n    for _, d := range dst {\n        fmt.Printf(\"%+v\\n\", d)\n    }\n\n    // Output:\n    // {I:2 St:aa}\n    // {I:22 St:aaaa}\n```\n\n### Copy between structs and maps\n\n  [Playground](https://go.dev/play/p/eS8RWB8dKmL)\n\n```go\n    type D struct {\n        I int  `copy:\"i\"`\n        U uint `copy:\"u\"`\n    }\n\n    src := map[string]any{\"i\": 1, \"u\": 2, \"s\": \"abc\"}\n    var dst D\n    err := deepcopy.Copy(\u0026dst, \u0026src)\n    if err != nil {\n        fmt.Println(\"error:\", err)\n    }\n    fmt.Printf(\"Result struct: %+v\\n\", dst)\n\n    src2 := D{I: 11, U: 22}\n    dst2 := map[string]any{}\n    err = deepcopy.Copy(\u0026dst2, \u0026src2)\n    if err != nil {\n        fmt.Println(\"error:\", err)\n    }\n    fmt.Printf(\"Result map: %+v\\n\", dst2)\n\n    // Output:\n    // Result struct: {I:1 U:2}\n    // Result map: map[i:11 u:22]\n```\n\n### Configure extra copying behaviors\n\n- Not allow to copy between `ptr` type and `value` (default is `allow`)\n\n  [Playground](https://go.dev/play/p/ZYzGaCNwp2i)\n\n```go\n    type S struct {\n        I  int\n        U  uint\n    }\n    type D struct {\n        I *int\n        U uint\n    }\n    src := []S{{I: 1, U: 2}, {I: 11, U: 22}}\n    var dst []D\n    err := deepcopy.Copy(\u0026dst, \u0026src, deepcopy.CopyBetweenPtrAndValue(false))\n    fmt.Println(\"error:\", err)\n\n    // Output:\n    // error: ErrTypeNonCopyable: int -\u003e *int\n```\n\n- Ignore ErrTypeNonCopyable, the process will not return that kind of error, but some copyings won't be performed.\n  \n  [Playground 1](https://go.dev/play/p/YPz49D_oiTY) /\n  [Playground 2](https://go.dev/play/p/DNrBJUP-rrM)\n\n```go\n    type S struct {\n        I []int\n        U uint\n    }\n    type D struct {\n        I int\n        U uint\n    }\n    src := []S{{I: []int{1, 2, 3}, U: 2}, {I: []int{1, 2, 3}, U: 22}}\n    var dst []D\n    // The copy will succeed with ignoring copy of field `I`\n    _ = deepcopy.Copy(\u0026dst, \u0026src, deepcopy.IgnoreNonCopyableTypes(true))\n\n    for _, d := range dst {\n        fmt.Printf(\"%+v\\n\", d)\n    }\n\n    // Output:\n    // {I:0 U:2}\n    // {I:0 U:22}\n```\n\n## Benchmarks\n\n### Go-DeepCopy vs ManualCopy vs Other Libs\n\nThis benchmark is done on go-deepcopy v1.6.0 using Go 1.24.2\n\n**Copy between 2 different struct types** \n  [Benchmark code](https://gist.github.com/tiendc/0a739fd880b9aac5373de95458d54808)\n\n```\nGo-DeepCopy\nGo-DeepCopy-10         \t 1734240\t       682.3 ns/op\t     344 B/op\t       4 allocs/op\nManualCopy\nManualCopy-10          \t32983267\t        35.59 ns/op\t      80 B/op\t       1 allocs/op\nJinzhuCopier\nJinzhuCopier-10        \t  146428\t      8138 ns/op\t     912 B/op\t      40 allocs/op\nulule/deepcopier\nulule/deepcopier-10    \t   47137\t     25717 ns/op\t   50752 B/op\t     550 allocs/op\nmohae/deepcopy\nmohae/deepcopy-10      \t  597488\t      1828 ns/op\t    1208 B/op\t      42 allocs/op\nbarkimedes/deepcopy\nbarkimedes/deepcopy-10 \t  528232\t      2206 ns/op\t    1464 B/op\t      15 allocs/op\nmitchellh/copystructure\nmitchellh/copystructure-10   123484\t      9545 ns/op\t    7592 B/op\t     191 allocs/op\n```\n\n**Copy between the same struct type**\n  [Benchmark code](https://gist.github.com/tiendc/502725af830d454382234e8dca22dbdf)\n\n```\nGo-DeepCopy\nGo-DeepCopy-10         \t 2693502\t       438.0 ns/op\t     248 B/op\t       4 allocs/op\nManualCopy\nManualCopy-10          \t36577604\t        32.17 ns/op\t      80 B/op\t       1 allocs/op\nJinzhuCopier\nJinzhuCopier-10        \t  187950\t      6468 ns/op\t     824 B/op\t      39 allocs/op\nulule/deepcopier\nulule/deepcopier-10    \t   50193\t     23170 ns/op\t   44768 B/op\t     486 allocs/op\nmohae/deepcopy\nmohae/deepcopy-10      \t 1000000\t      1083 ns/op\t     640 B/op\t      26 allocs/op\nbarkimedes/deepcopy\nbarkimedes/deepcopy-10 \t  886911\t      1345 ns/op\t     888 B/op\t      13 allocs/op\nmitchellh/copystructure\nmitchellh/copystructure-10   212216\t      5559 ns/op\t    4552 B/op\t     116 allocs/op\n```\n\n## Contributing\n\n- You are welcome to make pull requests for new functions and bug fixes.\n\n## License\n\n- [MIT License](LICENSE)\n\n[doc-img]: https://pkg.go.dev/badge/github.com/tiendc/go-deepcopy\n[doc]: https://pkg.go.dev/github.com/tiendc/go-deepcopy\n[gover-img]: https://img.shields.io/badge/Go-%3E%3D%201.18-blue\n[gover]: https://img.shields.io/badge/Go-%3E%3D%201.18-blue\n[ci-img]: https://github.com/tiendc/go-deepcopy/actions/workflows/go.yml/badge.svg\n[ci]: https://github.com/tiendc/go-deepcopy/actions/workflows/go.yml\n[cov-img]: https://codecov.io/gh/tiendc/go-deepcopy/branch/main/graph/badge.svg\n[cov]: https://codecov.io/gh/tiendc/go-deepcopy\n[rpt-img]: https://goreportcard.com/badge/github.com/tiendc/go-deepcopy\n[rpt]: https://goreportcard.com/report/github.com/tiendc/go-deepcopy\n","funding_links":[],"categories":["Go","Reflection"],"sub_categories":["HTTP Clients","HTTP客户端"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftiendc%2Fgo-deepcopy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftiendc%2Fgo-deepcopy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftiendc%2Fgo-deepcopy/lists"}