How to test if an interface{} is a map?

6,744 views
Skip to first unread message

Sean Russell

unread,
Oct 13, 2012, 9:53:47 AM10/13/12
to golan...@googlegroups.com
Hi,

How does one test if an interface{} value is a map when the map value type is unknown?

--- SER

minux

unread,
Oct 13, 2012, 10:07:12 AM10/13/12
to Sean Russell, golan...@googlegroups.com
On Sat, Oct 13, 2012 at 9:53 PM, Sean Russell <seaner...@gmail.com> wrote:
How does one test if an interface{} value is a map when the map value type is unknown?

Jesse McNelis

unread,
Oct 13, 2012, 10:07:27 AM10/13/12
to Sean Russell, golan...@googlegroups.com
On Sun, Oct 14, 2012 at 12:53 AM, Sean Russell <seaner...@gmail.com> wrote:
> How does one test if an interface{} value is a map when the map value type
> is unknown?

import (
"fmt"
"reflect"
)
func main() {
var a interface{}= make(map[string]string)
fmt.Println(reflect.TypeOf(a).Kind() == reflect.Map)
}

The rest of the reflect package will be useful in working out how to
use this unknown map.
http://golang.org/pkg/reflect/



--
=====================
http://jessta.id.au

Sean Russell

unread,
Oct 13, 2012, 10:09:50 AM10/13/12
to golan...@googlegroups.com, Sean Russell, jes...@jessta.id.au
On Saturday, October 13, 2012 10:07:41 AM UTC-4, Jesse McNelis wrote:
The rest of the reflect package will be useful in working out how to
use this unknown map.
http://golang.org/pkg/reflect/

I was afraid of that, but thanks.

--- SER 

Rémy Oudompheng

unread,
Oct 13, 2012, 10:13:44 AM10/13/12
to Sean Russell, golan...@googlegroups.com, jes...@jessta.id.au
Why did you need to do that?

Rémy.

Sean Russell

unread,
Oct 13, 2012, 10:27:57 AM10/13/12
to golan...@googlegroups.com, Sean Russell, jes...@jessta.id.au
On Saturday, October 13, 2012 10:13:53 AM UTC-4, Rémy Oudompheng wrote:
>> http://golang.org/pkg/reflect/
>
> I was afraid of that, but thanks.

Why did you need to do that?

I have some common code that I'd like to factor out into a utility function to reduce code duplication. I'm looping over chunked JSON responses from a server and am trying to aggregate the results in a arrays, for a number of different types.  The looping and aggregation code is identical for all of the types except for the type of the array in the map, so what I really want to end up with is a function signature:

// functionally: accum = append(accum, objMap[key]...)
func loopAndAggregate(key string, objMap interface{}, accum interface{})

such that I can:

func processFoos() []Foo {
   fooMap := make(map[string][]Foo)
   var foos []Foo
   loopAndAggregate("foos", fooMap, foos)
   return foos
}
func processBars()  []Bars {
   barMap := make(map[string][]Foo)
   var bars []Bar
   loopAndAggregate("foos", barMap, bars)
   return bars
}
 
--- SER

minux

unread,
Oct 13, 2012, 10:41:21 AM10/13/12
to Sean Russell, golan...@googlegroups.com, jes...@jessta.id.au
On Sat, Oct 13, 2012 at 10:27 PM, Sean Russell <seaner...@gmail.com> wrote:
I have some common code that I'd like to factor out into a utility function to reduce code duplication. I'm looping over chunked JSON responses from a server and am trying to aggregate the results in a arrays, for a number of different types.  The looping and aggregation code is identical for all of the types except for the type of the array in the map, so what I really want to end up with is a function signature:

// functionally: accum = append(accum, objMap[key]...)
func loopAndAggregate(key string, objMap interface{}, accum interface{})

such that I can:

func processFoos() []Foo {
   fooMap := make(map[string][]Foo)
   var foos []Foo
   loopAndAggregate("foos", fooMap, foos)
FYI: you will need to pass &foos to loopAndAggregate. 
   return foos
}

Rémy Oudompheng

unread,
Oct 13, 2012, 10:42:38 AM10/13/12
to Sean Russell, golan...@googlegroups.com, jes...@jessta.id.au
On 2012/10/13 Sean Russell <seaner...@gmail.com> wrote:
> I have some common code that I'd like to factor out into a utility function
> to reduce code duplication. I'm looping over chunked JSON responses from a
> server and am trying to aggregate the results in a arrays, for a number of
> different types.

You seem to want generic programming in Go, which is not available.
Attempts to emulate it will often result in weird code. Sometimes you
can achieve the same functionality while remaining idiomatic by
switching paradigms.

> The looping and aggregation code is identical for all of
> the types except for the type of the array in the map, so what I really want
> to end up with is a function signature:
>
> // functionally: accum = append(accum, objMap[key]...)
> func loopAndAggregate(key string, objMap interface{}, accum interface{})
>
>
> such that I can:
>
> func processFoos() []Foo {
> fooMap := make(map[string][]Foo)
> var foos []Foo
> loopAndAggregate("foos", fooMap, foos)
> return foos
> }

The example looks too simple to be interesting. Instead of repeating
for _, v := range fooMap { foos = append(foos, v...) }
you will be repeating
loopAndAggregate("foos", fooMap, foos)
which doesn't look like a saving, since it occupies roughly the same space.

Rémy.

Sean Russell

unread,
Oct 13, 2012, 10:48:17 AM10/13/12
to golan...@googlegroups.com, Sean Russell, jes...@jessta.id.au

On Saturday, October 13, 2012 10:42:46 AM UTC-4, Rémy Oudompheng wrote:
On 2012/10/13 Sean Russell <seaner...@gmail.com> wrote:
> I have some common code that I'd like to factor out into a utility function
> to reduce code duplication. I'm looping over chunked JSON responses from a
> server and am trying to aggregate the results in a arrays, for a number of
> different types.
...

The example looks too simple to be interesting. Instead of repeating
  for _, v := range fooMap { foos = append(foos, v...) }
you will be repeating
  loopAndAggregate("foos", fooMap, foos)
which doesn't look like a saving, since it occupies roughly the same space.

I implied a lot of code in the sake of simplicity.  loopAndAggregate is doing much more than the aggregation; it is making the REST server calls, interpreting responses, handling the exit cases (all data has been fetched), and looping if not all of the data has yet been fetched.  The aggregation is the least of what it does.  It is 53 lines of code which I'd rather not duplicate for each of the six or seven types of data I handle.

--- SER

Sean Russell

unread,
Oct 13, 2012, 11:22:20 AM10/13/12
to golan...@googlegroups.com, Sean Russell, jes...@jessta.id.au
In case any other reflection novices are curious about the solution (which, incidentally, for all of my fear of the reflect package, wasn't all that bad), I have a minimal, working, utterly non-error-checked proof of concept here.

--- SER
Reply all
Reply to author
Forward
0 new messages