Skip to content

Instantly share code, notes, and snippets.

@pmn
Last active August 7, 2021 19:12
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pmn/5374494 to your computer and use it in GitHub Desktop.
Save pmn/5374494 to your computer and use it in GitHub Desktop.
Convert an interface{} containing a slice of structs to [][]string (used in CSV serialization) [golang reflection example] Runnable example here: http://play.golang.org/p/ZSJRxkpFs9
// Convert an interface{} containing a slice of structs into [][]string.
func recordize(input interface{}) [][]string {
var records [][]string
var header []string // The first record in records will contain the names of the fields
object := reflect.ValueOf(input)
// The first record in the records slice should contain headers / field names
if object.Len() > 0 {
first := object.Index(0)
typ := first.Type()
for i := 0; i < first.NumField(); i++ {
header = append(header, typ.Field(i).Name)
}
records = append(records, header)
}
// Make a slice of objects to iterate through & populate the string slice
var items []interface{}
for i := 0; i < object.Len(); i++ {
items = append(items, object.Index(i).Interface())
}
// Populate the rest of the items into <records>
for _, v := range items {
item := reflect.ValueOf(v)
var record []string
for i := 0; i < item.NumField(); i++ {
itm := item.Field(i).Interface()
record = append(record, fmt.Sprintf("%v", itm))
}
records = append(records, record)
}
return records
}
@jamesajones
Copy link

have a set of structs which have fields of two types first is uint and second is slice of structs. In the method below am attempting to set up anonymous recursion through the various sub structs.
func HandleMsg() {
var msg = CreateK001Message()
t := reflect.ValueOf(&msg).Elem()
typeOfT := t.Type()
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
tag := typeOfT.Field(i).Tag
switch f.Kind() {
case reflect.Uint:
fmt.Printf("%d: %s %s = %v %+v\n", i, typeOfT.Field(i).Name, f.Type(), f.Interface(), tag)
case reflect.Slice:
fmt.Printf("%d: %s %s = %v %+v\n", i, typeOfT.Field(i).Name, f.Type(), f.Interface(), tag)
var res = recordize(f.Interface())
var nw []string
for j := 0; j < len(res[0]); j++ {
var field = res[0][j] + " = " + res[1][j]
nw = append(nw, field)
}
//handleSliceField(nw)
default:
}
}
}
In the Slice section I have used your method above to build a representation of the first []subsstruct but of course it is no longer a struct and I cannot process it as one.
From the f.Interface() I can get a string that is a json representation of this first level.
Is there any way to create an anonymous struct using your work or the string from f.Interface?

Copy link

ghost commented Dec 11, 2019

if it can help other people like it was for me

package convert

import (
	"reflect"
)

type PairKeyValue struct {
	Id    int
	Key   string
	Value int
}

// Convert an interface{} containing a slice of structs to []PairKeyValue

func ConvertInterface_A(input interface{}) []PairKeyValue {

	var records []PairKeyValue
	object := reflect.ValueOf(input)

	// Make a slice of objects to iterate through and populate the string slice
	var items []interface{}
	for i := 0; i < object.Len(); i++ {
		items = append(items, object.Index(i).Interface())
	}

	// Populate the rest of the items into <records>
	for _, v := range items {
		item := reflect.ValueOf(v)
		var record PairKeyValue

		itm0 := item.Field(0).Interface()
		itm1 := item.Field(1).Interface()
		itm2 := item.Field(2).Interface()

		record.Id = itm0.(int)
		record.Key = itm1.(string)
		record.Value = itm2.(int)

		records = append(records, record)
	}
	return records
}

// Convert an interface{} containing a struct to PairKeyValue

func ConvertInterface_B(input interface{}) PairKeyValue {

	var record PairKeyValue
	item := reflect.ValueOf(input)

	// Populate the rest of the items into <records>
	itm0 := item.Field(0).Interface()
	itm1 := item.Field(1).Interface()
	itm2 := item.Field(2).Interface()

	record.Id = itm0.(int)
	record.Key = itm1.(string)
	record.Value = itm2.(int)

	return record
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment