Problem:
How can we iterate over a data structure (array or map) in Go without having exact knowledge of its type?
Failed Attempt:
The code below attempts to iterate over an interface representing either a map or an array and execute a function on each item, but it fails due to type checking issues.
func DoTheThingToAllTheThings(data_interface interface{}) int { var numThings int switch data := data_interface.(type) { case map[interface{}]interface{}: numThings = len(data) // ... case []interface{}: numThings = len(data) // ... default: fmt.Println("uh oh!") } return numThings }
Solution:
The fmt.Printf("%vn", data_interface) function provides a way to iterate over the data structure without type-casting.
func PrintData(data_interface interface{}) { fmt.Printf("%v\n", data_interface) }
This works because the %v verb in fmt.Printf uses reflection to determine the type of the argument and print it accordingly.
Reflection in Go:
The fmt.Printf function internally uses the reflect package to inspect the type of the argument and decide how to format it. The reflect.ValueOf(arg) returns a reflect.Value object, which represents the actual value of the argument, and reflect.TypeOf(arg) returns the type of the value.
Example:
The following code reflects a Board struct, then reconstitutes it into a new variable of the same type.
type Board struct { Tboard [9]string Player1 Player Player2 Player } func main() { myBoard := makeBoard() v := reflect.ValueOf(*myBoard) t := v.Type() var b2 Board b2 = v.Interface().(Board) fmt.Printf("v converted back to: %#v\n", b2) }
Note:
In order to use reflection, the data structure's type must beexported, which means it must start with an uppercase letter.
The above is the detailed content of How Can I Iterate Over Unknown Data Structures in Go?. For more information, please follow other related articles on the PHP Chinese website!