Re: [go-nuts] A proposal: Simplification of `map[string]interface{}` with Assumptive Maps

Skip to first unread message

Rémy Oudompheng

Jun 5, 2013, 2:46:55 AM6/5/13
to, golang-nuts
On 2013/6/5 <> wrote:
> A proposal: Simplification of `map[string]interface{}` with Assumptive Maps
> We write a lot of Go code, and most of it seems to be
> `map[string]interface{}`. Therefore we propose a new language feature
> called "Assumptive Maps".

I'm not sure where you get that name "assumptive maps" from.

The proposal would seriously modify the meaning of the following code:

package main

import "fmt"

var label = "hello"

func main() {
world := "world"
{label: fmt.Sprint("value: %s", world)}

> What do you think?
> We would very much appreciate any feedback or thoughts regarding this idea,
> and would be prepared to contribute code to make it happen if the people
> want it.

The idea seems very dificult to accept because of what I said.
Note however, that in virtue of the "type elision in composite
literal" feature of Go 1, the following code is legal and work as you
would expect:

package main

import "fmt"

var label = "hello"

func main() {
world := "world"
s := []map[string]string{
{label: fmt.Sprintf("value: %s", world)},
fmt.Printf("%+v", s)


Jesse McNelis

Jun 5, 2013, 2:48:24 AM6/5/13
to, golang-nuts
On Wed, Jun 5, 2013 at 2:44 PM, <> wrote:
> A proposal: Simplification of `map[string]interface{}` with Assumptive Maps
> We write a lot of Go code, and most of it seems to be `map[string]interface{}`. Therefore we propose a new language feature called "Assumptive Maps".

If most of your Go code is map[string]interface{} then you're doing
something wrong.
It sounds like you're trying to write Javascript in Go. This is a bad idea.
Go is a statically typed language, use this to your advantage instead
of trying to fight it.


Kevin Gillette

Jun 5, 2013, 3:50:27 AM6/5/13
Assuming that it will determine the value (and perhaps key) types based on the observed "assumptive literal", it'd be really easy to break code with minor changes. For example:

== Before ==

m := {1: 2, 3: 4}
var x map[int]int = m // works

== After ==
m := {1: 2, 3: 4.5}
var x map[int]int = m // broken, since m is now inferred to be either map[int]interface{} or map[int]float64, depending on defined semantics.

On Tuesday, June 4, 2013 10:44:05 PM UTC-6, wrote:
A proposal: Simplification of `map[string]interface{}` with Assumptive Maps

We write a lot of Go code, and most of it seems to be `map[string]interface{}`.  Therefore we propose a new language feature called "Assumptive Maps". 

What do they look like?
Instead of

  • mymap := map[string]string{"Name":"Mat"}
  • var mymap map[int]string := map[int]string{1: "Mat", 2: "Tyler"}

we could write:

  • mymap1 := {"Name": "Mat"}
  • /* mymap1 would be of type map[string]interface{} or 
  •    map[string]string depending on the options below */

  • var mymap2 map[int]string = {1: "Mat", 2: "Tyler"}
  • /* mymap2 would be of type map[int]string - since the developer
  •    has explicitally assigned a type to the lvalue */

What are they?
An assumptive map is a compile-time shortcut for defining a map. At compile time, the type of the map is determined by examining the values assigned to the map.

Selecting types

  • Option one
  • The types can be determined by the content of the shortcut map.  For example, if all keys are string we know it'll be `map[string]...`.  If all values are `int` the compiler knows it will be `map[string]int`

  • The compiler would throw an error if there are type mismatches, and force the developer to make a decision.

  • Option two
  • Another option, is that everything defined with `{...}` assumptive syntax always becomes `map[string]interface{}`, unless the lvalue already has a type defined.

  • This provides complete consistency and means that maps won't change type depending on the data.  If the user were to pass a value of a type other than string as the key, the compiler would issue an error.

  • However, if the user already has a variable with a specific type of map, the `{...}` syntax would use that type instead of just assuming `map[string]interface{}`.

  • var mymap map[int]string
  • mymap = {1: "Mat", 2: "Tyler"}
  • /* this is OK */

  • If the user were to specify a value of a type other than one defined (or assumed) as the key, the compiler would issue an error.

  • mymap := {1: "Mat", 2: "Tyler"}
  • /* this would be an error, because map[string]interface{} is
  •    assumed by default */

  • Easier to type and read
  • Familiar; especially since it's so similar to JSON

  • The code is potentially unclear and would require outside knowledge of the feature
Other ideas

  • Something similar could be done for arrays of maps;  `[{"name":"Mat"},{"name":"Tyler"}]`

roger peppe

Jun 5, 2013, 6:05:30 PM6/5/13
to Kevin,, golang-nuts

One trick I've used in the past to save typing in this kind of situation is to define a type.
Eg type m map[string]interface{}

Then you can write m{"foo": 5} and or is assignment-compatible with map[string]interface{}.

It's not flawless (when they're nested, something might be confused by the m type), but it's a useful technique and good in other situations too.

You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to
For more options, visit

Mat Ryer

Jun 5, 2013, 1:42:31 PM6/5/13
to Kevin Gillette,

You're right.  I actually prefer the `{…}` being a shortcut for `map[string]interface{}` option.  Which would insist the keys are strings, but the values could be anything.


David DENG

Jun 6, 2013, 12:09:16 PM6/6/13
I may suggest a more conservative type deduction as follow:

for the following assignment:

m := {a: b, c: d}

the rule for the map is simple and clear: the type of the key is the type of a, as if the deductive type for key := a. If the type for c is different, an error raised. Similar rule for type of the value.

map[string]interface{} should be used rarely.


Gustavo Niemeyer

Jun 6, 2013, 12:27:35 PM6/6/13
On Wed, Jun 5, 2013 at 1:44 AM, <> wrote:
> A proposal: Simplification of `map[string]interface{}` with Assumptive Maps
> We write a lot of Go code, and most of it seems to be
> `map[string]interface{}`.

This is definitely not true, at least for the code I read and write.

That said, the idea of shortening composite literals further has
already received serious attention from the core development team, and

gustavo @

Mat Ryer

Jun 6, 2013, 1:05:32 PM6/6/13
to Gustavo Niemeyer,
Thanks for the link.

Jason Moiron

Jun 6, 2013, 2:45:14 PM6/6/13
When I first started writing Go code, I did this a lot:

type dict map[string]interface{}

mgo/bson does this too, for instance:

These days, I tend to stay away from maps except when absolutely necessary.  Still, there are problem domains where lots of them are absolutely necessary, and I see no problem with creating this kind of shortcut type alias.  There are a lot of drawbacks to relying on `map[string]interface{}`, but sometimes you really have lots of nails lying around and you really do need a hammer.

All that being said, I don't think there is a set of assumptions/behaviors which is both simple enough and useful enough for type inference on map literals.

-- Jason

On Wednesday, June 5, 2013 12:44:05 AM UTC-4, wrote:
A proposal: Simplification of `map[string]interface{}` with Assumptive Maps

Kevin Gillette

Jun 6, 2013, 3:08:53 PM6/6/13
to, Kevin Gillette,
In that case, rog's suggestion is equivalent to yours, but can be done now, and only costs an extra byte -- e.g. m{"a": 1, "b": 2} instead of {"a": 1, "b": 2}

Mat Ryer

Jun 6, 2013, 6:23:51 PM6/6/13
to Kevin Gillette,
I have tried this before, and didn't like the fact that I had to always cast to my fake 'm' type.  Which, outside of the package would end up being packagename.M.  You can see how verbose it becomes quite quickly.

Jan Mercl

Jun 7, 2013, 4:36:35 AM6/7/13
to, golang-nuts
On Wed, Jun 5, 2013 at 6:44 AM, <> wrote:
> A proposal: Simplification of `map[string]interface{}` with Assumptive Maps

I don't like the idea. Consider this valid code:

package main

import "fmt"

func main() {
mmmmmm := map[int]string{1: "foo", 42: "bar"}
m := map[int]interface{}{1: "foo", 42: "bar"}
ssssssssss := [50]string{1: "foo", 42: "bar"}


Which type, of the three above, would `qux := {1: "foo", 42: "bar"}`
be in your proposal?
Why that one?
How the other two would have to be written then? Only using the long/full form?
If so, then why (only) one of them is blessed and allowed to be shortened?



Jun 7, 2013, 11:19:27 AM6/7/13
That can be
    m1 := map...{1: "foo", 42: "bar"} // -> map[int]string, use strict types
    ss1 := [...]string{1: "foo", 42: "bar"} // already done
    ss2 := [...]...{1: "foo", 42: "bar"} // same as ss1
Sort of type inference for data.

пятница, 7 июня 2013 г., 12:36:35 UTC+4 пользователь Jan Mercl написал:

Mat Ryer

Jun 7, 2013, 11:33:55 AM6/7/13
to Jan Mercl, golang-nuts
I would actually prefer the shorthand to always be `map[string]interface{}` (a normal flexible map) and would write the longhand version if I wanted to be specific about types.

Dart has this feature, you can do this:

var map = { "something": 123, "something_else": true }

OR if you want specific types:

Map<string, num> m = { "something": 123 }

The same in Go would be:

map := {"something": 123, "something_else": true}
map := map[string]int{"something": 123}

I think arrays should also work:

list := [{"something":123},{"something-else":456}]

The assumed type of list would be []map[string]interface{}.

Anybody who wanted to be specific can continue to do so (this wouldn't break old code)


Martin Angers

Jun 7, 2013, 12:17:35 PM6/7/13
to, Jan Mercl,
Dart and Go have very different targets. Dart tries to replace a dynamic language (javascript), Go positions itself as a systems language (C/C++, statically typed). I definitely don't like the idea of defaulting to map[string]interface{} for the short form. It means := would sometimes infer the (static) type, other times infer what is basically a dynamic type.

I actually think the language is fine as is for the type inference and literal declarations. This is definitely not a pain point for me.

Mat Ryer

Jun 7, 2013, 1:24:08 PM6/7/13
to Martin Angers,, Jan Mercl
You are right about Go and Dart having different targets, my point is only that people can cope perfectly well with having default behaviour, and being specific if they need to.

Henrik Johansson

Jun 7, 2013, 1:57:52 PM6/7/13
to Mat Ryer, Jan Mercl, golang-nuts, Martin Angers

Some default behaviours are just worse than others...

Peter Bourgon

Jun 9, 2013, 3:57:05 AM6/9/13
to Mat Ryer, Jan Mercl, golang-nuts
On Fri, Jun 7, 2013 at 5:33 PM, Mat Ryer <> wrote:
> I would actually prefer the shorthand to always be `map[string]interface{}` (a normal flexible map)

To echo other posters: it is a mistake to call this a "normal" map,
because its presence is generally a bad smell. Speaking personally,
the only time I've ever used such a thing is when I'm [un]marshaling
JSON and am being lazy -- the interface{} standing as evidence for the
Reply all
Reply to author
0 new messages