Any one line solution to copy a golang map

I have a very big map. I don’t want to iterate and copy it to another one. Is there any other solution to this?
One I can think of is to push map data in DB and the retrieve it back but this would add an extra query which is costly.

Also what would be a viable solution.

A SO recommends to copy the map in a loop: https://stackoverflow.com/a/23058707/9455968

If it is so big, why don’t you find some other solution without copying it? I mean is it absolutely necessary to copy? Otherwise there is no other way than copy each element in a loop as this is reference type, like said above.

Comprising data

Using a for loop and copying the data is likely to be the fastest and easiest solution to understand. If you insist on trying something else, you could try converting to Json and back but I don’t recommend it.

I want to copy because maps are by reference and I don’t want to pass that map.

Why don’t you make a struct receiver containing this map (do not export the map) and a lookup or getter (read-only) method on it? Something like this:

type MyMap struct {
	myHugeMap map[string]string
}

func (m *MyMap) get(i string) (string, error) {
	e, ok := m[i]
	if !ok {
		return "", fmt.Errorf("element %s not found", i)
	}
	return e, nil
}

Of course, this should be in a separate package and you should pass around pointer to this struct.

Don’t understand your use case. But if you’re going to copy it why not just maintain duplicate maps from the beginning doing something like: https://play.golang.org/p/nQP7EUn9R2d

The fastest serialization approach would be to encode/decode the map using “encoding/gob”.

Yes, I tried gob but I have to register all types which is untidy and I don’t know my map(is a filter from frontend) which might be complex. So, either I find all types and register in gob?

Thanks, json marshalling and unmarshalling works. Also I shifted to a easier solution to iterate and copy
But would have to test load.

func copy(originalMap map[string]interface{}) map[string]interface{} {
	newMap := make(map[string]interface{})
	for key, value := range originalMap {
		newMap[key] = value
	}
	return newMap
}
func  appendWith(toAppend bson.M, filter map[string]interface{}) error {
	value := filter["cond"]
	marshallValue, err := json.Marshal(value)
	if err != nil {
		return errors.Wrap(err, "json marshall")
	}
	var unmarshallValue []interface{}
	err = json.Unmarshal(marshallValue, &unmarshallValue)
	if err != nil {
		return errors.Wrap(err, "json unmarshall")
	}
	var res []interface{}
	res = append(res, unmarshallValue...)
	_ = append(res, toAppend)
	return nil
}

Well if you’ve got values with lots of new types, then you’d have to register them, but if it’s just a few new types then it’s not much work given the speed of encoding/gob vs encoding/json.

But if you’re creating the initial map from unknown data, then I assume it’s a standard map[string]interface{} value. If so, this would require no type registration.

Here: https://play.golang.org/p/it0mLk1vd8f.

Note: if you’re gob encoding/decoding from a struct definition then there’s no registration required: https://play.golang.org/p/Pv0tPAcU74v.

I ran into a problem with this.
https://play.golang.org/p/MRpurSATQuV

You see only one level copying being done. Internally we can replace things and it will still reference to original map.

Honestly I’m not sure I or anyone else can help you much more without additional context. We all know that you want to copy a map, that you are worried about internal code altering data in the map, and that you are apparently using a map[string]interface{} (which could already be considered a code smell), but that doesn’t really paint a picture of what you are doing and why you are doing it, so it’s really hard to give sound advice.

It would be like you asking me what kind of tires to buy for your car and me trying to give you advice without knowing if you live where it snows all the time, part of the year, or is always sunny. Or maybe you are planning on taking your car to a race track and need an entirely different type of tire. The point is, I could try to give you some vague generic advice, but at the end of the day that’s all it will be - vague generic advice that probably isn’t too useful.

If you absolutely want to just clone the map every time, you can encode it into JSON then back into a new map variable and that should deep clone it every time (as far as I’m aware), but it is going to be somewhat slow. Likely faster than querying the DB over and over again, but still not blazing fast.

If you want us to give you better advice I believe we need to really understand more about what you are doing so we can help you come up with a viable solution that may or may not include cloning a map[string]interface{}.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.