My take on this is that this decision was purely pragmatic: Go is a very down-to-Earth language (as opposed to other — "more purist" — languages), and one interesting property of some real-world map implementations is that mere accessing them for reading might update their internal representation (!). Say, they might gather and store some statistic on their usage, or they might rebalance an underlying tree which holds the value buckets etc. Allowing a "const map" to exist would mean explicitly specifying a set of complicated constraints on it in the language spec — most possibly requiring implementations to have two map implementations.
You can also try looking at it from another angle: consider a string constant. Such thing might be easily embedded into the .rodata
section of the resulting binary and be actually represented by the address of that data in memory (well, strings in Go are more complicated but let's ignore that detail). That is, a constant string can be truly "static": it's just a series of static R/O bytes in memory — as simple as that.
Conversely, a map is a highly complicated beast powered by an intricate machinery, and each map is a special complex object instantiated at runtime. That's why you cannot even just declare a map and use it: you must make()
it first—just like channels, and for the same reason.
Again, some hack could possibly be done to support constant maps.
Say, an implementation could sort the keys of your map up front, serialize it (with values) into a contigous region of R/O data and then use binary search at runtime to look the values up. That would be woefully ineffective for large maps / certain key patterns but would supposedly work.
Still, that would be a specialized map implementation completely different from the "normal" one. I think Go devs decided the tradeoff is not worth possible benefit.
Two followup notes:
As you can see, you can relatively easily emulate a readonly map:
have a slice literal of some struct types embedding both keys and values,
presorted on the keys, and wrap it in a function which performs a binary
search on the key.
I prefer to consider Go's constants a bit like macros in a C-like
languages: they are untyped and feel like being textual (they are not
but I'm speaking about feeling after all) ;-)
Be sure to read this for a great overview.