FAQ
Hi,

I am making a function that getting interface{} as parameter and have
switch type to check type.
The problem comes when I want to loop through any map with any type of
value it has.
But I found the problem that I cannot do that without type assertion.
Is there any other way to do without declaring every case of map with its
specific value types?

Here is my current code:

func serialize(value interface{}) string{


     result := "<value>"
     switch value.(type) {
     case string:
       result += fmt.Sprintf("<string>%s</string>", value.(string))
     case int:
       result += fmt.Sprintf("<int>%d</int>", value)
     case map[string]interface{}:
       result += "<struct>"
       for k, v := range value.(map[string]interface{}) {
         result += "<member>"
         result += fmt.Sprintf("<name>%s</name>", k)
         result += serialize(v)
         result += "</member>"
       }
       result += "</struct>"
     default:
         log.Fatal("Cannot serialise: ", value)
     }
     result += "</value>"
     return res
}


So, the above code is working fine if I give it map[string]interface{} as
parameter.
But it won't for other map[string]anytype such as "map[string]string",
"map[string]int", etc.

I was thinking about using reflect in default case to check if it is map
and then do for loop but I got stuck there.

Below is the snippet changed from above code only "default" case

default:
   tmpVal:=reflect.ValueOf(value)
   if tmpVal.Kind() == reflect.Map{
     result+="<struct>"
     for k, v := range tmpVal { <-- I won't be able to do for loop w/o
doing type assertion correctly but I actually don't know whether map value
is int, string, float, etc...
       result +="<member>"
       result +=fmt.Sprintf("<name>%s</name>",k)
       result += string(v)
       result += "</member>"
     }
     result+="</struct>"
   }else{
      log.Fatal("Cannot serialise: ", value)
   }

--
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

  • Frits van Bommel at Jul 24, 2014 at 7:17 am

    On Thursday, July 24, 2014 9:07:48 AM UTC+2, Theeraphol Wattanavekin wrote:
    Hi,

    I am making a function that getting interface{} as parameter and have
    switch type to check type.
    The problem comes when I want to loop through any map with any type of
    value it has.
    But I found the problem that I cannot do that without type assertion.
    Is there any other way to do without declaring every case of map with its
    specific value types?

    Here is my current code: [snip]
    So, the above code is working fine if I give it map[string]interface{} as
    parameter.But it won't for other map[string]anytype such as
    "map[string]string", "map[string]int", etc.

    I was thinking about using reflect in default case to check if it is map
    and then do for loop but I got stuck there.

    Below is the snippet changed from above code only "default" case

    default:
    tmpVal:=reflect.ValueOf(value)
    if tmpVal.Kind() == reflect.Map{
    result+="<struct>"
    for k, v := range tmpVal { <-- I won't be able to do for loop w/o
    doing type assertion correctly but I actually don't know whether map value
    is int, string, float, etc...
    I think you're looking for Value.MapKeys()
    <http://golang.org/src/pkg/reflect/value.go?s=37314:37346#L1219>.
         for _, k := range tmpVal.MapKeys() { // Ignore index because it's a
    meaningless slice index, not the map index.
             v := tmpVal.MapIndex(k)

    result +="<member>"
    result +=fmt.Sprintf("<name>%s</name>",k)
    result += string(v)
    result += "</member>"
    }
    result+="</struct>"
    }else{
    log.Fatal("Cannot serialise: ", value)
    }
    --
    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.
  • Theeraphol Wattanavekin at Jul 24, 2014 at 7:30 am
    I am also trying to do type assertion for every case as below but also get
    the error as well:

    func serialize(value interface{}) string {
         result := "<value>"
         switch asserted_value := value.(type) {
         case string:
           result += fmt.Sprintf("<string>%s</string>", asserted_value)
         case int, int8, int16, int32, int64, uint, uint8, uint16, uint32,
    uint64:
           result += fmt.Sprintf("<int>%d</int>", asserted_value)
         case float32, float64:
           result += fmt.Sprintf("<float>%f</float>", asserted_value)
         case map[string]interface{}:
           result += "<struct>"
           for k, v := range asserted_value {
             result += "<member>"
             result += fmt.Sprintf("<name>%s</name>", k)
             result += serialize(v)
             result += "</member>"
           }
           result += "</struct>"
         case map[string]string, map[string]int, map[string]int8,
    map[string]int16, map[string]int32, map[string]int64,
           map[string]uint, map[string]uint8, map[string]uint16,
    map[string]uint32, map[string]uint64,

           map[string]float32, map[string]float64:
           result += "<struct>"
         for k, v := range asserted_value { << -- error here "cannot range
    over asserted_value (type interface {})"
             result += "<member>"
             result += fmt.Sprintf("<name>%s</name>", k)
             result += serialize(v)
             result += "</member>"
           }
           result += "</struct>"

         default:
           log.Fatal("Cannot serialise: ", value)
         }
         result += "</value>"
         return result
       }


    On 24 July 2014 16:06, Theeraphol Wattanavekin wrote:

    Hi,

    I am making a function that getting interface{} as parameter and have
    switch type to check type.
    The problem comes when I want to loop through any map with any type of
    value it has.
    But I found the problem that I cannot do that without type assertion.
    Is there any other way to do without declaring every case of map with its
    specific value types?

    Here is my current code:

    func serialize(value interface{}) string{


    result := "<value>"
    switch value.(type) {
    case string:
    result += fmt.Sprintf("<string>%s</string>", value.(string))
    case int:
    result += fmt.Sprintf("<int>%d</int>", value)
    case map[string]interface{}:
    result += "<struct>"
    for k, v := range value.(map[string]interface{}) {
    result += "<member>"
    result += fmt.Sprintf("<name>%s</name>", k)
    result += serialize(v)
    result += "</member>"
    }
    result += "</struct>"
    default:
    log.Fatal("Cannot serialise: ", value)
    }
    result += "</value>"
    return res
    }


    So, the above code is working fine if I give it map[string]interface{} as
    parameter.
    But it won't for other map[string]anytype such as "map[string]string",
    "map[string]int", etc.

    I was thinking about using reflect in default case to check if it is map
    and then do for loop but I got stuck there.

    Below is the snippet changed from above code only "default" case

    default:
    tmpVal:=reflect.ValueOf(value)
    if tmpVal.Kind() == reflect.Map{
    result+="<struct>"
    for k, v := range tmpVal { <-- I won't be able to do for loop w/o
    doing type assertion correctly but I actually don't know whether map value
    is int, string, float, etc...
    result +="<member>"
    result +=fmt.Sprintf("<name>%s</name>",k)
    result += string(v)
    result += "</member>"
    }
    result+="</struct>"
    }else{
    log.Fatal("Cannot serialise: ", value)
    }
    --
    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.
  • Frits van Bommel at Jul 24, 2014 at 7:44 am

    On Thursday, July 24, 2014 9:17:28 AM UTC+2, Frits van Bommel wrote:
    I think you're looking for Value.MapKeys()
    <http://golang.org/src/pkg/reflect/value.go?s=37314:37346#L1219>.
    Sorry, better link: Value.MapKeys()
    <http://golang.org/pkg/reflect/#Value.MapKeys> (documentation, not source
    code)

    Here's a full example that does what I think you're trying to do:
    http://play.golang.org/p/yi1jHyEqqq
    Note the use of k.Interface() and v.Interface() to get interface{} values
    that fmt can handle properly, and %v in the format string because they
    might not be string-like types.

    It's still not ideal code (bytes.Buffer
    <http://golang.org/pkg/bytes/#Buffer> is your friend, repeated string
    concatenations are usually slower) and you could even use encoding/xml to
    do what you want:
       http://play.golang.org/p/8t3_KUboYk

    Also, it's usually better to use the site linked above (play.golang.org)
    for code examples, especially relatively large ones like yours.
    On Thursday, July 24, 2014 9:30:27 AM UTC+2, Theeraphol Wattanavekin wrote:

    I am also trying to do type assertion for every case as below but also get
    the error as well:

    func serialize(value interface{}) string {
    result := "<value>"
    switch asserted_value := value.(type) {

    [snip other cases]
    case map[string]string, map[string]int, map[string]int8,
    map[string]int16, map[string]int32, map[string]int64,
    map[string]uint, map[string]uint8, map[string]uint16,
    map[string]uint32, map[string]uint64,

    map[string]float32, map[string]float64:
    result += "<struct>"
    for k, v := range asserted_value { << -- error here "cannot range
    over asserted_value (type interface {})"
    That won't work because you specified multiple types. asserted_value has
    the asserted type only in cases with a *single* type. In other cases it's
    just the original interface type asserted on.

    result += "<member>"
    result += fmt.Sprintf("<name>%s</name>", k)
    result += serialize(v)
    result += "</member>"
    }
    result += "</struct>"

    default:
    log.Fatal("Cannot serialise: ", value)
    }
    result += "</value>"
    return result
    }

    --
    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.
  • Theeraphol Wattanavekin at Jul 24, 2014 at 8:01 am
    Thank you very much, Frits van Bommel!!

    I have tried it and it solved my problem :)

    On Thursday, July 24, 2014 4:44:37 PM UTC+9, Frits van Bommel wrote:
    On Thursday, July 24, 2014 9:17:28 AM UTC+2, Frits van Bommel wrote:

    I think you're looking for Value.MapKeys()
    <http://golang.org/src/pkg/reflect/value.go?s=37314:37346#L1219>.
    Sorry, better link: Value.MapKeys()
    <http://golang.org/pkg/reflect/#Value.MapKeys> (documentation, not source
    code)

    Here's a full example that does what I think you're trying to do:
    http://play.golang.org/p/yi1jHyEqqq
    Note the use of k.Interface() and v.Interface() to get interface{} values
    that fmt can handle properly, and %v in the format string because they
    might not be string-like types.

    It's still not ideal code (bytes.Buffer
    <http://golang.org/pkg/bytes/#Buffer> is your friend, repeated string
    concatenations are usually slower) and you could even use encoding/xml to
    do what you want:
    http://play.golang.org/p/8t3_KUboYk

    Also, it's usually better to use the site linked above (play.golang.org)
    for code examples, especially relatively large ones like yours.
    On Thursday, July 24, 2014 9:30:27 AM UTC+2, Theeraphol Wattanavekin wrote:

    I am also trying to do type assertion for every case as below but also
    get the error as well:

    func serialize(value interface{}) string {
    result := "<value>"
    switch asserted_value := value.(type) {

    [snip other cases]
    case map[string]string, map[string]int, map[string]int8,
    map[string]int16, map[string]int32, map[string]int64,
    map[string]uint, map[string]uint8, map[string]uint16,
    map[string]uint32, map[string]uint64,

    map[string]float32, map[string]float64:
    result += "<struct>"
    for k, v := range asserted_value { << -- error here "cannot range
    over asserted_value (type interface {})"
    That won't work because you specified multiple types. asserted_value has
    the asserted type only in cases with a *single* type. In other cases it's
    just the original interface type asserted on.

    result += "<member>"
    result += fmt.Sprintf("<name>%s</name>", k)
    result += serialize(v)
    result += "</member>"
    }
    result += "</struct>"

    default:
    log.Fatal("Cannot serialise: ", value)
    }
    result += "</value>"
    return result
    }

    --
    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
postedJul 24, '14 at 7:07a
activeJul 24, '14 at 8:01a
posts5
users2
websitegolang.org

People

Translate

site design / logo © 2022 Grokbase