FAQ
For a map that has a nil key (and a value associated with it, of course):
mapp := map[interface{}]interface{}{
      nil: "a",
}

Accessing it’s nil key directly works:
fmt.Println("key[nil]:", mapp[nil])
But using reflection it doesn’t - how to do this?
rmapp := reflect.ValueOf(mapp)
rkey := reflect.ValueOf(interface{}(nil))
rval := rmapp.MapIndex(rmapp.MapIndex(rkey)) // panic: runtime error: invalid memory address or nil pointer dereference
fmt.Println("key[nil]:", rval)
Non-working code here:
https://play.golang.org/p/sCPpmpOUJw



--
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 golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Ian Lance Taylor at Jan 7, 2015 at 2:56 pm

    On Wed, Jan 7, 2015 at 6:27 AM, wrote:
    For a map that has a nil key (and a value associated with it, of course):

    mapp := map[interface{}]interface{}{
    nil: "a",
    }

    Accessing it’s nil key directly works:

    fmt.Println("key[nil]:", mapp[nil])

    But using reflection it doesn’t - how to do this?

    rmapp := reflect.ValueOf(mapp)
    rkey := reflect.ValueOf(interface{}(nil))
    rval := rmapp.MapIndex(rmapp.MapIndex(rkey)) // panic: runtime error:
    invalid memory address or nil pointer dereference
    fmt.Println("key[nil]:", rval)

    Non-working code here:
    https://play.golang.org/p/sCPpmpOUJw
    I think the panic with a runtime error is a bug in the reflect
    package. It should panic with some reflect error instead. Please
    open an issue for this (http://golang.org/issue/new). Thanks.

    In general you can't directly use an interface type with ValueOf.
    This is because ValueOf takes an interface type itself, and the
    original interface type is lost. You can make your program work by
    using a pointer and a dereference.

      empty := interface{}(nil)
      rkey := reflect.ValueOf(&empty).Elem()

    Ian

    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Roger peppe at Jan 7, 2015 at 5:01 pm
    I agree that the panic doesn't produce a great error message,
    but other than that, the behaviour of the reflect package is
    correct as documented AFAICS.

    The unexpected thing is that the semantics of MapIndex are not what
    you might expect. In Go, indexing a map with a non-existent key
    returns a value with the same type as the map elements, but MapIndex
    does not behave that way - it returns a zero (invalid) value when the
    element does not exist. I presume that's to avoid the need for MapIndex
    to return two values.

    To get the usual semantics, you'd need something like:

        func MapIndex(v, key reflect.Value) (reflect.Value, bool) {
             elem := v.MapIndex(key)
             if elem.IsValid() {
                  return elem, true
             }
             return reflect.Zero(v.Type().Elem()), false
         }

    Note also that reflect.ValueOf(nil) does not produce a valid Value
    with type interface{}. You'd need something like
    reflect.Zero(interfaceType) where
    interfaceType = reflect.TypeOf((*interface{})(nil)).Elem().

    Here's the example changed to demonstrate map index with a nil interface{}
    value:

    https://play.golang.org/p/pj248V071u

    Here's some code demonstrating that MapIndex returns an invalid value
    for non-existent elements (as documented in the refect docs):

    https://play.golang.org/p/fXX-mOHTJA

       cheers,
         rog.
    On 7 January 2015 at 14:56, Ian Lance Taylor wrote:
    On Wed, Jan 7, 2015 at 6:27 AM, wrote:

    For a map that has a nil key (and a value associated with it, of course):

    mapp := map[interface{}]interface{}{
    nil: "a",
    }

    Accessing it’s nil key directly works:

    fmt.Println("key[nil]:", mapp[nil])

    But using reflection it doesn’t - how to do this?

    rmapp := reflect.ValueOf(mapp)
    rkey := reflect.ValueOf(interface{}(nil))
    rval := rmapp.MapIndex(rmapp.MapIndex(rkey)) // panic: runtime error:
    invalid memory address or nil pointer dereference
    fmt.Println("key[nil]:", rval)

    Non-working code here:
    https://play.golang.org/p/sCPpmpOUJw
    I think the panic with a runtime error is a bug in the reflect
    package. It should panic with some reflect error instead. Please
    open an issue for this (http://golang.org/issue/new). Thanks.

    In general you can't directly use an interface type with ValueOf.
    This is because ValueOf takes an interface type itself, and the
    original interface type is lost. You can make your program work by
    using a pointer and a dereference.

    empty := interface{}(nil)
    rkey := reflect.ValueOf(&empty).Elem()

    Ian

    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Gima at Jan 7, 2015 at 5:26 pm
    Thank you both. The solution materialized for accessing the nil-key of a
    map by:

          refmap.MapIndex(reflect.Zero(refmap.Type().Key()))
    On 7.1.2015 19:01, roger peppe wrote:
    I agree that the panic doesn't produce a great error message,
    but other than that, the behaviour of the reflect package is
    correct as documented AFAICS.

    The unexpected thing is that the semantics of MapIndex are not what
    you might expect. In Go, indexing a map with a non-existent key
    returns a value with the same type as the map elements, but MapIndex
    does not behave that way - it returns a zero (invalid) value when the
    element does not exist. I presume that's to avoid the need for MapIndex
    to return two values.

    To get the usual semantics, you'd need something like:

    func MapIndex(v, key reflect.Value) (reflect.Value, bool) {
    elem := v.MapIndex(key)
    if elem.IsValid() {
    return elem, true
    }
    return reflect.Zero(v.Type().Elem()), false
    }

    Note also that reflect.ValueOf(nil) does not produce a valid Value
    with type interface{}. You'd need something like
    reflect.Zero(interfaceType) where
    interfaceType = reflect.TypeOf((*interface{})(nil)).Elem().

    Here's the example changed to demonstrate map index with a nil
    interface{} value:

    https://play.golang.org/p/pj248V071u

    Here's some code demonstrating that MapIndex returns an invalid value
    for non-existent elements (as documented in the refect docs):

    https://play.golang.org/p/fXX-mOHTJA

    cheers,
    rog.

    On 7 January 2015 at 14:56, Ian Lance Taylor wrote:
    On Wed, Jan 7, 2015 at 6:27 AM, wrote:

    For a map that has a nil key (and a value associated with it, of course):
    mapp := map[interface{}]interface{}{
    nil: "a",
    }

    Accessing it’s nil key directly works:

    fmt.Println("key[nil]:", mapp[nil])

    But using reflection it doesn’t - how to do this?

    rmapp := reflect.ValueOf(mapp)
    rkey := reflect.ValueOf(interface{}(nil))
    rval := rmapp.MapIndex(rmapp.MapIndex(rkey)) // panic: runtime error:
    invalid memory address or nil pointer dereference
    fmt.Println("key[nil]:", rval)

    Non-working code here:
    https://play.golang.org/p/sCPpmpOUJw
    I think the panic with a runtime error is a bug in the reflect
    package. It should panic with some reflect error instead. Please
    open an issue for this (http://golang.org/issue/new). Thanks.

    In general you can't directly use an interface type with ValueOf.
    This is because ValueOf takes an interface type itself, and the
    original interface type is lost. You can make your program work by
    using a pointer and a dereference.

    empty := interface{}(nil)
    rkey := reflect.ValueOf(&empty).Elem()

    Ian

    --
    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 golang-nuts+unsubscribe@googlegroups.com
    For more options, visit https://groups.google.com/d/optout.
    --
    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 golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedJan 7, '15 at 2:27p
activeJan 7, '15 at 5:26p
posts4
users3
websitegolang.org

People

Translate

site design / logo © 2022 Grokbase