How to check if a variable is String or Array

Hi,
in my template,
i loop over a variable that normally is an array, but sometime not.

e.g.

the array is a feature list

normally it can be for example

features = [“red”,“hard”,“sweet”]

but sometime the variable can be a string, for example

feature = “There is no any particular feature”.

when i loop over features, template rendering fails if feature is not an array.

i tried to understand if index exists, i tried to find in documentation and in the forum, but i don’t find anything good.

Can someone help me?

thanks.

Why not make it an array all the time?

because i Can’t.

at the beginning this variabile was a string , some time ago It become an Array and now these values must Be used together.

i Need to avoid to use a range if the variabile Is not the Array version

Hey, @Andrea_Bisello I’m not entirely sure I understand what you’re trying to accomplish, but if can make these all arrays you can get the first item in the array (thus treating it like a string) with index, like this:

{{ feature := index (.Params.features ) 0 }}

I didn’t test it, but something like that should work. Hope that helps, and if not, maybe you can clarify a bit more.

Thanks for your help,
but in some of my content, feature is a string, in other feature is an array.
i cannot restore content.
i the template i need to loop over the feature array if feature is array, or i need to print the feature string is feature is a string.

pseudo code :

{{ if .Params.feature is Array }}
// loop
{{ end }}

{{ if .Params.feature is String }}
// print
{{ end }}

In the original post you have “feature” and “features”. Those are two different variables, so you should be okay, ne? You can check for features, and if it isn’t set, you can load feature.

And if that isn’t how it is set up, maybe you ought to set it up that way.

I’m also surprised that there’s no mechanism for determining data types (like reflect.TypeOf), but I think I found a work around.

Using isset with -1 for the second parameter seems to consistently return true for arrays, and false for everything else. Passing 0, it returns true for a non-empty array, but still returns false for an empty array:

isset    nonExistant -1: false
isset     emptyArray -1: true
isset  notEmptyArray -1: true
isset      emptyHash -1: false
isset   notEmptyHash -1: false
isset    emptyString -1: false
isset notEmptyString -1: false
isset     zeroNumber -1: false
isset  notZeroNumber -1: false
isset    nonExistant  0: false
isset     emptyArray  0: false
isset  notEmptyArray  0: true
isset      emptyHash  0: false
isset   notEmptyHash  0: false
isset    emptyString  0: false
isset notEmptyString  0: false
isset     zeroNumber  0: false
isset  notZeroNumber  0: false

This does produce warnings, but it seems to work.

WARNING: calling IsSet with unsupported type "invalid" (<nil>) will always return false.

WARNING: calling IsSet with unsupported type "string" (string) will always return false.

WARNING: calling IsSet with unsupported type "int64" (int64) will always return false.

So, in the strictest sense, using isset with -1 seems to work as an “is array” function. However, I’d be inclined to use 0 as that’s probably good enough for most cases and it’s maybe a bit less of a hack.

2 Likes

I recently explored a bit to get this missing feature working for my debug purposes, and I ended up with a debugprint.html partial which I share here:

That led to this issue:

Given my lack of Go coding knowledge and time to learn enough to come up with a PR to do something about that, that issue still stands.

1 Like

To make @kaushalmodi’s findings a specific answer to the OP’s question:

{{ $type := (printf "%T" Params.feature) }} // insert variable here

{{ if eq $type "[]interface {}" }}
// do something with array
{{ end }}

{{ if eq $type "string" }}
// do something with string
{{ end }}