Search code examples
gosliceterratest

How to convert the string representation of a Terraform set of strings to a slice of strings


I've a terratest where I get an output from terraform like so s := "[a b]". The terraform output's value = toset([resource.name]), it's a set of strings.

Apparently fmt.Printf("%T", s) returns string. I need to iterate to perform further validation.

I tried the below approach but errors!

var v interface{}
if err := json.Unmarshal([]byte(s), &v); err != nil {
    fmt.Println(err)
}

My current implementation to convert to a slice is:

s := "[a b]"
s1 := strings.Fields(strings.Trim(s, "[]"))
for _, v:= range s1 {
    fmt.Println("v -> " + v)
}

Looking for suggestions to current approach or alternative ways to convert to arr/slice that I should be considering. Appreciate any inputs. Thanks.


Solution

  • Actually your current implementation seems just fine.

    You can't use JSON unmarshaling because JSON strings must be enclosed in double quotes ".

    Instead strings.Fields does just that, it splits a string on one or more characters that match unicode.IsSpace, which is \t, \n, \v. \f, \r and .

    Moeover this works also if terraform sends an empty set as [], as stated in the documentation:

    returning [...] an empty slice if s contains only white space.

    ...which includes the case of s being empty "" altogether.

    In case you need additional control over this, you can use strings.FieldsFunc, which accepts a function of type func(rune) bool so you can determine yourself what constitutes a "space". But since your input string comes from terraform, I guess it's going to be well-behaved enough.

    There may be third-party packages that already implement this functionality, but unless your program already imports them, I think the native solution based on the standard lib is always preferrable.


    unicode.IsSpace actually includes also the higher runes 0x85 and 0xA0, in which case strings.Fields calls FieldsFunc(s, unicode.IsSpace)