31

I'm using the github.com/fatih/structs package to convert values of all fields of a struct into []interface{} with the toValues() function. See here. This works fine, but eventually I want to write the values to a csv file by using the csv package. The csv.Write() function requires []string as input.

So in short: how can I easily convert the output of toValues() into an array of strings?

icza
  • 389,944
  • 63
  • 907
  • 827
Rogier Lommers
  • 2,263
  • 3
  • 24
  • 38

3 Answers3

50

You can't simply convert []interface{} to []string even if all the values are of concrete type string, because those 2 types have different memory layout / representation. For details see Cannot convert []string to []interface {}.

You have to define how you want values of different types to be represented by string values.

The easiest and sensible way would be to iterate over the values, and use fmt.Sprint() to obtain a string representation of each, e.g.:

t := []interface{}{
    "zero",
    1, 2.0, 3.14,
    []int{4, 5},
    struct{ X, Y int }{6, 7},
}
fmt.Println(t)

s := make([]string, len(t))
for i, v := range t {
    s[i] = fmt.Sprint(v)
}
fmt.Println(s)
fmt.Printf("%q\n", s)

Output (try it on the Go Playground):

[zero 1 2 3.14 [4 5] {6 7}]
[zero 1 2 3.14 [4 5] {6 7}]
["zero" "1" "2" "3.14" "[4 5]" "{6 7}"]
Community
  • 1
  • 1
icza
  • 389,944
  • 63
  • 907
  • 827
  • Thanks; didn't thought about using fmt.Sprint. Working fine now! – Rogier Lommers May 17 '17 at 16:22
  • 1
    wow, this helped me so much... but still I hope for a more robust way with assertion – Alireza Soori Dec 17 '19 at 07:27
  • 2
    @AlirezaSoori you can have this with type assertion: just change `fmt.Sprint(v)` with `v.(string)`. – Eric Lindsey Dec 28 '19 at 09:01
  • @icza - This is weird - I've tried using this answer for a similar problem, but I simply can't access the []interface{} when iterating, it returns a "cannot range over foobar (type interface{})" error. If you have time I'd greatly appreciate your input - https://stackoverflow.com/questions/70611033/cant-convert-interface-to-string-in-go – Lou Jan 06 '22 at 17:24
  • 1
    This is convoluted+ugly. Go needs to have cleaner methods for such bulk conversions. It becomes nightmare to work with JSON otherwise. :( – Manish Jul 22 '22 at 07:13
  • @DanieleTesta Because the question asks how to convert `[]interface{}` to `[]string`. `fmt.Sprintf("%v", inter)` produces a single `string`, not a `[]string`. – icza Aug 19 '22 at 08:09
0

you can, just do:

    func text(msg ...interface{}) string {
        return fmt.Sprintf("%+v", msg...)
    }
-1

Use fmt.Sprintf to convert an interface value to a string. In fact, this technique can be used to get a string representation of any data structure.

Here is the code sample,

var Foo interface{} = "Value"

str := fmt.Sprintf("%v", Foo)
Chikku Jacob
  • 2,114
  • 1
  • 18
  • 33