README.md
1# Mergo
2
3
4[![GoDoc][3]][4]
5[![GitHub release][5]][6]
6[![GoCard][7]][8]
7[![Build Status][1]][2]
8[![Coverage Status][9]][10]
9[![Sourcegraph][11]][12]
10[![FOSSA Status][13]][14]
11
12[![GoCenter Kudos][15]][16]
13
14[1]: https://travis-ci.org/imdario/mergo.png
15[2]: https://travis-ci.org/imdario/mergo
16[3]: https://godoc.org/github.com/imdario/mergo?status.svg
17[4]: https://godoc.org/github.com/imdario/mergo
18[5]: https://img.shields.io/github/release/imdario/mergo.svg
19[6]: https://github.com/imdario/mergo/releases
20[7]: https://goreportcard.com/badge/imdario/mergo
21[8]: https://goreportcard.com/report/github.com/imdario/mergo
22[9]: https://coveralls.io/repos/github/imdario/mergo/badge.svg?branch=master
23[10]: https://coveralls.io/github/imdario/mergo?branch=master
24[11]: https://sourcegraph.com/github.com/imdario/mergo/-/badge.svg
25[12]: https://sourcegraph.com/github.com/imdario/mergo?badge
26[13]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fimdario%2Fmergo.svg?type=shield
27[14]: https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_shield
28[15]: https://search.gocenter.io/api/ui/badge/github.com%2Fimdario%2Fmergo
29[16]: https://search.gocenter.io/github.com/imdario/mergo
30
31A helper to merge structs and maps in Golang. Useful for configuration default values, avoiding messy if-statements.
32
33Mergo merges same-type structs and maps by setting default values in zero-value fields. Mergo won't merge unexported (private) fields. It will do recursively any exported one. It also won't merge structs inside maps (because they are not addressable using Go reflection).
34
35Also a lovely [comune](http://en.wikipedia.org/wiki/Mergo) (municipality) in the Province of Ancona in the Italian region of Marche.
36
37## Status
38
39It is ready for production use. [It is used in several projects by Docker, Google, The Linux Foundation, VMWare, Shopify, etc](https://github.com/imdario/mergo#mergo-in-the-wild).
40
41### Important note
42
43Please keep in mind that a problematic PR broke [0.3.9](//github.com/imdario/mergo/releases/tag/0.3.9). I reverted it in [0.3.10](//github.com/imdario/mergo/releases/tag/0.3.10), and I consider it stable but not bug-free. Also, this version adds suppot for go modules.
44
45Keep in mind that in [0.3.2](//github.com/imdario/mergo/releases/tag/0.3.2), Mergo changed `Merge()`and `Map()` signatures to support [transformers](#transformers). I added an optional/variadic argument so that it won't break the existing code.
46
47If you were using Mergo before April 6th, 2015, please check your project works as intended after updating your local copy with ```go get -u github.com/imdario/mergo```. I apologize for any issue caused by its previous behavior and any future bug that Mergo could cause in existing projects after the change (release 0.2.0).
48
49### Donations
50
51If Mergo is useful to you, consider buying me a coffee, a beer, or making a monthly donation to allow me to keep building great free software. :heart_eyes:
52
53<a href='https://ko-fi.com/B0B58839' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://az743702.vo.msecnd.net/cdn/kofi1.png?v=0' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
54[![Beerpay](https://beerpay.io/imdario/mergo/badge.svg)](https://beerpay.io/imdario/mergo)
55[![Beerpay](https://beerpay.io/imdario/mergo/make-wish.svg)](https://beerpay.io/imdario/mergo)
56<a href="https://liberapay.com/dario/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a>
57
58### Mergo in the wild
59
60- [moby/moby](https://github.com/moby/moby)
61- [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)
62- [vmware/dispatch](https://github.com/vmware/dispatch)
63- [Shopify/themekit](https://github.com/Shopify/themekit)
64- [imdario/zas](https://github.com/imdario/zas)
65- [matcornic/hermes](https://github.com/matcornic/hermes)
66- [OpenBazaar/openbazaar-go](https://github.com/OpenBazaar/openbazaar-go)
67- [kataras/iris](https://github.com/kataras/iris)
68- [michaelsauter/crane](https://github.com/michaelsauter/crane)
69- [go-task/task](https://github.com/go-task/task)
70- [sensu/uchiwa](https://github.com/sensu/uchiwa)
71- [ory/hydra](https://github.com/ory/hydra)
72- [sisatech/vcli](https://github.com/sisatech/vcli)
73- [dairycart/dairycart](https://github.com/dairycart/dairycart)
74- [projectcalico/felix](https://github.com/projectcalico/felix)
75- [resin-os/balena](https://github.com/resin-os/balena)
76- [go-kivik/kivik](https://github.com/go-kivik/kivik)
77- [Telefonica/govice](https://github.com/Telefonica/govice)
78- [supergiant/supergiant](supergiant/supergiant)
79- [SergeyTsalkov/brooce](https://github.com/SergeyTsalkov/brooce)
80- [soniah/dnsmadeeasy](https://github.com/soniah/dnsmadeeasy)
81- [ohsu-comp-bio/funnel](https://github.com/ohsu-comp-bio/funnel)
82- [EagerIO/Stout](https://github.com/EagerIO/Stout)
83- [lynndylanhurley/defsynth-api](https://github.com/lynndylanhurley/defsynth-api)
84- [russross/canvasassignments](https://github.com/russross/canvasassignments)
85- [rdegges/cryptly-api](https://github.com/rdegges/cryptly-api)
86- [casualjim/exeggutor](https://github.com/casualjim/exeggutor)
87- [divshot/gitling](https://github.com/divshot/gitling)
88- [RWJMurphy/gorl](https://github.com/RWJMurphy/gorl)
89- [andrerocker/deploy42](https://github.com/andrerocker/deploy42)
90- [elwinar/rambler](https://github.com/elwinar/rambler)
91- [tmaiaroto/gopartman](https://github.com/tmaiaroto/gopartman)
92- [jfbus/impressionist](https://github.com/jfbus/impressionist)
93- [Jmeyering/zealot](https://github.com/Jmeyering/zealot)
94- [godep-migrator/rigger-host](https://github.com/godep-migrator/rigger-host)
95- [Dronevery/MultiwaySwitch-Go](https://github.com/Dronevery/MultiwaySwitch-Go)
96- [thoas/picfit](https://github.com/thoas/picfit)
97- [mantasmatelis/whooplist-server](https://github.com/mantasmatelis/whooplist-server)
98- [jnuthong/item_search](https://github.com/jnuthong/item_search)
99- [bukalapak/snowboard](https://github.com/bukalapak/snowboard)
100- [janoszen/containerssh](https://github.com/janoszen/containerssh)
101
102## Install
103
104 go get github.com/imdario/mergo
105
106 // use in your .go code
107 import (
108 "github.com/imdario/mergo"
109 )
110
111## Usage
112
113You can only merge same-type structs with exported fields initialized as zero value of their type and same-types maps. Mergo won't merge unexported (private) fields but will do recursively any exported one. It won't merge empty structs value as [they are zero values](https://golang.org/ref/spec#The_zero_value) too. Also, maps will be merged recursively except for structs inside maps (because they are not addressable using Go reflection).
114
115```go
116if err := mergo.Merge(&dst, src); err != nil {
117 // ...
118}
119```
120
121Also, you can merge overwriting values using the transformer `WithOverride`.
122
123```go
124if err := mergo.Merge(&dst, src, mergo.WithOverride); err != nil {
125 // ...
126}
127```
128
129Additionally, you can map a `map[string]interface{}` to a struct (and otherwise, from struct to map), following the same restrictions as in `Merge()`. Keys are capitalized to find each corresponding exported field.
130
131```go
132if err := mergo.Map(&dst, srcMap); err != nil {
133 // ...
134}
135```
136
137Warning: if you map a struct to map, it won't do it recursively. Don't expect Mergo to map struct members of your struct as `map[string]interface{}`. They will be just assigned as values.
138
139Here is a nice example:
140
141```go
142package main
143
144import (
145 "fmt"
146 "github.com/imdario/mergo"
147)
148
149type Foo struct {
150 A string
151 B int64
152}
153
154func main() {
155 src := Foo{
156 A: "one",
157 B: 2,
158 }
159 dest := Foo{
160 A: "two",
161 }
162 mergo.Merge(&dest, src)
163 fmt.Println(dest)
164 // Will print
165 // {two 2}
166}
167```
168
169Note: if test are failing due missing package, please execute:
170
171 go get gopkg.in/yaml.v2
172
173### Transformers
174
175Transformers allow to merge specific types differently than in the default behavior. In other words, now you can customize how some types are merged. For example, `time.Time` is a struct; it doesn't have zero value but IsZero can return true because it has fields with zero value. How can we merge a non-zero `time.Time`?
176
177```go
178package main
179
180import (
181 "fmt"
182 "github.com/imdario/mergo"
183 "reflect"
184 "time"
185)
186
187type timeTransformer struct {
188}
189
190func (t timeTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error {
191 if typ == reflect.TypeOf(time.Time{}) {
192 return func(dst, src reflect.Value) error {
193 if dst.CanSet() {
194 isZero := dst.MethodByName("IsZero")
195 result := isZero.Call([]reflect.Value{})
196 if result[0].Bool() {
197 dst.Set(src)
198 }
199 }
200 return nil
201 }
202 }
203 return nil
204}
205
206type Snapshot struct {
207 Time time.Time
208 // ...
209}
210
211func main() {
212 src := Snapshot{time.Now()}
213 dest := Snapshot{}
214 mergo.Merge(&dest, src, mergo.WithTransformers(timeTransformer{}))
215 fmt.Println(dest)
216 // Will print
217 // { 2018-01-12 01:15:00 +0000 UTC m=+0.000000001 }
218}
219```
220
221
222## Contact me
223
224If I can help you, you have an idea or you are using Mergo in your projects, don't hesitate to drop me a line (or a pull request): [@im_dario](https://twitter.com/im_dario)
225
226## About
227
228Written by [Dario Castañé](http://dario.im).
229
230## Top Contributors
231
232[![0](https://sourcerer.io/fame/imdario/imdario/mergo/images/0)](https://sourcerer.io/fame/imdario/imdario/mergo/links/0)
233[![1](https://sourcerer.io/fame/imdario/imdario/mergo/images/1)](https://sourcerer.io/fame/imdario/imdario/mergo/links/1)
234[![2](https://sourcerer.io/fame/imdario/imdario/mergo/images/2)](https://sourcerer.io/fame/imdario/imdario/mergo/links/2)
235[![3](https://sourcerer.io/fame/imdario/imdario/mergo/images/3)](https://sourcerer.io/fame/imdario/imdario/mergo/links/3)
236[![4](https://sourcerer.io/fame/imdario/imdario/mergo/images/4)](https://sourcerer.io/fame/imdario/imdario/mergo/links/4)
237[![5](https://sourcerer.io/fame/imdario/imdario/mergo/images/5)](https://sourcerer.io/fame/imdario/imdario/mergo/links/5)
238[![6](https://sourcerer.io/fame/imdario/imdario/mergo/images/6)](https://sourcerer.io/fame/imdario/imdario/mergo/links/6)
239[![7](https://sourcerer.io/fame/imdario/imdario/mergo/images/7)](https://sourcerer.io/fame/imdario/imdario/mergo/links/7)
240
241
242## License
243
244[BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE).
245
246
247[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fimdario%2Fmergo.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_large)
248