joinElements joins a slice of items with the given separator. It uses [strings.Join] if it's a slice of strings, otherwise uses [fmt.Sprint] to join each item to the output.
(elems any, sep string)
| 105 | // [strings.Join] if it's a slice of strings, otherwise uses [fmt.Sprint] |
| 106 | // to join each item to the output. |
| 107 | func joinElements(elems any, sep string) (string, error) { |
| 108 | if elems == nil { |
| 109 | return "", nil |
| 110 | } |
| 111 | |
| 112 | if ss, ok := elems.([]string); ok { |
| 113 | return strings.Join(ss, sep), nil |
| 114 | } |
| 115 | |
| 116 | switch rv := reflect.ValueOf(elems); rv.Kind() { //nolint:exhaustive // ignore: too many options to make exhaustive |
| 117 | case reflect.Array, reflect.Slice: |
| 118 | var b strings.Builder |
| 119 | for i := range rv.Len() { |
| 120 | if i > 0 { |
| 121 | b.WriteString(sep) |
| 122 | } |
| 123 | _, _ = fmt.Fprint(&b, rv.Index(i).Interface()) |
| 124 | } |
| 125 | return b.String(), nil |
| 126 | |
| 127 | case reflect.Map: |
| 128 | var out []string |
| 129 | for _, k := range rv.MapKeys() { |
| 130 | out = append(out, fmt.Sprint(rv.MapIndex(k).Interface())) |
| 131 | } |
| 132 | // Not ideal, but trying to keep a consistent order |
| 133 | sort.Strings(out) |
| 134 | return strings.Join(out, sep), nil |
| 135 | |
| 136 | default: |
| 137 | return "", fmt.Errorf("expected slice, got %T", elems) |
| 138 | } |
| 139 | } |