loops - Using reflection in Go, how to iterate a known slice - Stack Overflow

admin2025-05-02  0

With

    m := map[string]any{"a": 1, "b": 2, "c": []int{2, 3, 4}}
    v := reflect.ValueOf(m)

How to iterate through "c" in v?

See /play/p/KQ_UNjm-Vqd

package main

import (
    "fmt"
    "reflect"
)

func main() {
    m := map[string]any{"a": 1, "b": 2, "c": []int{2, 3, 4}}
    v := reflect.ValueOf(m)

    // Access the "c" key
    cKey := reflect.ValueOf("c")
    cValue := v.MapIndex(cKey)

    if cValue.IsValid() && cValue.Kind() == reflect.Slice {
        fmt.Println("Iterating through 'c':")
        for i := 0; i < cValue.Len(); i++ {
            fmt.Println(cValue.Index(i).Interface())
        }
    } else {
        fmt.Println("'c' is not a valid slice or key does not exist.")
    }

    if !cValue.IsValid() {
        fmt.Println("Key 'c' not found in the map")
        return
    }
    if cValue.Kind() != reflect.Slice {
        fmt.Println("Value for key 'c' is not a slice")
        return
    }
}

With

    m := map[string]any{"a": 1, "b": 2, "c": []int{2, 3, 4}}
    v := reflect.ValueOf(m)

How to iterate through "c" in v?

See https://go.dev/play/p/KQ_UNjm-Vqd

package main

import (
    "fmt"
    "reflect"
)

func main() {
    m := map[string]any{"a": 1, "b": 2, "c": []int{2, 3, 4}}
    v := reflect.ValueOf(m)

    // Access the "c" key
    cKey := reflect.ValueOf("c")
    cValue := v.MapIndex(cKey)

    if cValue.IsValid() && cValue.Kind() == reflect.Slice {
        fmt.Println("Iterating through 'c':")
        for i := 0; i < cValue.Len(); i++ {
            fmt.Println(cValue.Index(i).Interface())
        }
    } else {
        fmt.Println("'c' is not a valid slice or key does not exist.")
    }

    if !cValue.IsValid() {
        fmt.Println("Key 'c' not found in the map")
        return
    }
    if cValue.Kind() != reflect.Slice {
        fmt.Println("Value for key 'c' is not a slice")
        return
    }
}
Share Improve this question asked Jan 2 at 3:00 xptxpt 23.3k45 gold badges154 silver badges246 bronze badges 4
  • cValue represents the interface, not the underlying slice - use .Elem() to get a Value for the underlying slice. There's gotta be a dupe around here somewhere, but I'm not familiar with the standard Go dupe targets. – user2357112 Commented Jan 2 at 3:09
  • Thanks @user2357112. Fixed in go.dev/play/p/v2LMvkRKrCz – xpt Commented Jan 2 at 3:15
  • @xpt What exactly do you know about the value associated to "c"? Only that it's a slice of some unknown element type? Or do you also know that the element type is int? Because, in the latter case, you don't need reflection; a simple type assertion will do. – jub0bs Commented Jan 2 at 9:53
  • No @jub0bs. int is for demo and simplicity only. The actual c is a json struct that I haven't able to exhaust all its possible fields yet. – xpt Commented Jan 3 at 0:17
Add a comment  | 

2 Answers 2

Reset to default 1

(I spent way too long in this)

package main

import (
"fmt"
"reflect"
)

func main() {
m := map[string]any{"a": 1, "b": 2, "c": []int{2, 3, 4}}
v := reflect.ValueOf(m)

// Access the "c" key
cKey := reflect.ValueOf("c")
cValue := v.MapIndex(cKey)

if !cValue.IsValid() {
    fmt.Println("Key 'c' not found in the map. ")
    return
}

// If the value is an interface, unwrap it
if cValue.Kind() == reflect.Interface {
    cValue = cValue.Elem()
}

if cValue.Kind() != reflect.Slice {
    fmt.Println("Value for key 'c' is not a slice. ")
    return
}

fmt.Println("Iterating... ")
for i := 0; i < cValue.Len(); i++ {
    fmt.Printf("Element %d: %v\n", i, cValue.Index(i).Interface())
}
}

To iterate over a reflect.Value representing a Map, we can utilize the MapKeys method from the reflect package. Here's a complete example:

// Check if the reflect.Value represents a Map
if v.Kind() == reflect.Map {
    // Get all the keys in the map as a slice of reflect.Value
    keys := v.MapKeys()
    for _, key := range keys {
        // Convert the reflect.Value representation of the key back to its original type
        keyStr, ok := key.Interface().(string)
        if !ok {
            fmt.Printf("Key is not a string: %v\n", key)
            continue
        }

        // Retrieve the value associated with the key
        value := v.MapIndex(key)

        // Extract the underlying value from reflect.Value and print the key-value pair
        fmt.Printf("Key: %s, Value: %v\n", keyStr, value.Interface())
    }
} else {
    fmt.Println("v is not a map")
}

Live Code

Key Points

  1. Check v.Kind() Before Using Map-Specific Methods Methods like MapKeys() or MapIndex() will panic on non-map values

Sources:

  • Reflect.Value docs
  • Reflect.MapKeys docs
  • Reflect.MapIndex docs
转载请注明原文地址:http://anycun.com/QandA/1746135695a92066.html