title: Golang merge deeply two maps
body: <p>I'm trying to deep copy of two yaml, trying to simulate the behaviour that use <a href="https://github.com/helm/" rel="nofollow noreferrer">helm</a> when you pass multiple values during an installation.
  Because of a project restriction, I'm getting the values from strings and not directly form yamls.
  The problem is that the copy is not done as I expect.</p>
  <p>I add an example:</p>
  <p><strong>value1</strong>:</p>
  <pre><code>test:
    somekey: 1
    otherkey: 2
  othertest:
    somekey: 3
  </code></pre>
  <p><strong>value2</strong>:</p>
  <pre><code>test:
    somekey: NEWVALUE1
    NEWKEY: NEWVALUE2
  </code></pre>
  <p><strong>EXPECTED OUTPUT</strong>:</p>
  <pre><code>test:
    somekey: NEWVALUE1
    otherkey: 2
    NEWKEY: NEWVALUE2
  othertest:
    somekey: 3
  </code></pre>
  <p><strong>RESULT</strong>:</p>
  <pre><code>othertest:
    somekey: 3
  test:
    NEWKEY: NEWVALUE2
    somekey: NEWVALUE1
  </code></pre>
  <p>So as you can see in the example, it is overwritting all the <code>test</code> map, when I would like to merge both <code>test</code> maps.</p>
  <p>Here I add the code I'm using</p>
  <pre><code>package main
  
  import (
      &quot;github.com/prometheus/common/log&quot;
      &quot;gopkg.in/yaml.v2&quot;
  )
  
  func main() {
      value1 := &quot;test:\n  somekey: 1\n  otherkey: 2\nothertest:\n  somekey: 3&quot;
      value2 := &quot;test:\n  somekey: NEWVALUE1\n  NEWKEY: NEWVALUE2&quot;
      values := []string{value1, value2}
      result, err := getValuesFromString(values)
      if err != nil {
          log.Info(err)
      }
  
      //expecting: test:\n  somekey: NEWVALUE1\n  otherkey: 2\n  NEWKEY: NEWVALUE2\nothertest:\n  somekey: 3
      //getting: othertest:\n  somekey: 3\ntest:\n  NEWKEY: NEWVALUE2\n  somekey: NEWVALUE1\n
      log.Info(&quot;FINAL VALUES: &quot; + result)
  }
  
  func getValuesFromString(values []string) (string, error) {
  
      var resultValues map[string]interface{}
      var bs []byte
      for _, value := range values {
          log.Info(values)
          var override map[string]interface{}
          bs = []byte(value)
  
          if err := yaml.Unmarshal(bs, &amp;override); err != nil {
              log.Info(err)
              continue
          }
  
          //check if is nil. This will only happen for the first value
          if resultValues == nil {
              resultValues = override
          } else {
              resultValues = mergeMaps(resultValues, override)
          }
      }
  
      bs, err := yaml.Marshal(resultValues)
      if err != nil {
          log.Info(err)
          return &quot;&quot;, err
      }
  
      return string(bs), nil
  }
  
  func mergeMaps(a, b map[string]interface{}) map[string]interface{} {
      out := make(map[string]interface{}, len(a))
      for k, v := range a {
          out[k] = v
      }
      for k, v := range b {
          if v, ok := v.(map[string]interface{}); ok {
              if bv, ok := out[k]; ok {
                  if bv, ok := bv.(map[string]interface{}); ok {
                      out[k] = mergeMaps(bv, v)
                      continue
                  }
              }
          }
          out[k] = v
      }
      return out
  }
  
  </code></pre>
  <p>I think the error is that I'm generating incorrectly the map from the string <code>var resultValues map[string]interface{}</code>, but I didn't find the way to convert the string to a map</p>