diff options
| author | Dave Henderson <dhenderson@gmail.com> | 2017-11-02 22:13:15 -0400 |
|---|---|---|
| committer | Dave Henderson <dhenderson@gmail.com> | 2017-11-02 22:13:15 -0400 |
| commit | 22922aeb84e96fe387cec69c9d5aaef1492ff4d6 (patch) | |
| tree | 84b7c5b9943ce5476ffd652410b19b4329140708 | |
| parent | 75f0194e8566a43a12155208bbef5474b2aad01b (diff) | |
Fixing conv.Join to handle non-interface{} arrays
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
| -rw-r--r-- | conv/conv.go | 47 | ||||
| -rw-r--r-- | conv/conv_test.go | 5 |
2 files changed, 37 insertions, 15 deletions
diff --git a/conv/conv.go b/conv/conv.go index 464df7dd..38d88683 100644 --- a/conv/conv.go +++ b/conv/conv.go @@ -36,6 +36,11 @@ func Join(in interface{}, sep string) string { var a []interface{} a, ok = in.([]interface{}) + if !ok { + var err error + a, err = interfaceSlice(in) + ok = err == nil + } if ok { b := make([]string, len(a)) for i := range a { @@ -48,6 +53,18 @@ func Join(in interface{}, sep string) string { return "" } +func interfaceSlice(slice interface{}) ([]interface{}, error) { + s := reflect.ValueOf(slice) + if s.Kind() != reflect.Slice { + return nil, fmt.Errorf("interfaceSlice given a non-slice type %T", s) + } + ret := make([]interface{}, s.Len()) + for i := 0; i < s.Len(); i++ { + ret[i] = s.Index(i).Interface() + } + return ret, nil +} + // Has determines whether or not a given object has a property with the given key func Has(in interface{}, key string) bool { av := reflect.ValueOf(in) @@ -61,28 +78,28 @@ func Has(in interface{}, key string) bool { } func toString(in interface{}) string { + if in == nil { + return "nil" + } if s, ok := in.(string); ok { return s } if s, ok := in.(fmt.Stringer); ok { return s.String() } - if i, ok := in.(int); ok { - return strconv.Itoa(i) - } - if u, ok := in.(uint64); ok { - return strconv.FormatUint(u, 10) - } - if f, ok := in.(float64); ok { - return strconv.FormatFloat(f, 'f', -1, 64) - } - if b, ok := in.(bool); ok { - return strconv.FormatBool(b) - } - if in == nil { - return "nil" + val := reflect.Indirect(reflect.ValueOf(in)) + switch val.Kind() { + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + return strconv.FormatInt(val.Int(), 10) + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint, reflect.Uint64: + return strconv.FormatUint(val.Uint(), 10) + case reflect.Float32, reflect.Float64: + return strconv.FormatFloat(val.Float(), 'f', -1, 64) + case reflect.Bool: + return strconv.FormatBool(val.Bool()) + default: + return fmt.Sprintf("%s", in) } - return fmt.Sprintf("%s", in) } // MustParseInt - wrapper for strconv.ParseInt that returns 0 in the case of error diff --git a/conv/conv_test.go b/conv/conv_test.go index 5150fbcd..aa35fd49 100644 --- a/conv/conv_test.go +++ b/conv/conv_test.go @@ -36,6 +36,11 @@ func TestJoin(t *testing.T) { assert.Equal(t, "foo,\nbar", Join([]interface{}{"foo", "bar"}, ",\n")) // Join handles all kinds of scalar types too... assert.Equal(t, "42-18446744073709551615", Join([]interface{}{42, uint64(18446744073709551615)}, "-")) + assert.Equal(t, "42,100", Join([]int{42, 100}, ",")) + assert.Equal(t, "42,100", Join([]int64{42, 100}, ",")) + assert.Equal(t, "42,100", Join([]uint64{42, 100}, ",")) + assert.Equal(t, "true,false", Join([]bool{true, false}, ",")) + assert.Equal(t, "1,2", Join([]float64{1, 2}, ",")) assert.Equal(t, "1,,true,3.14,foo,nil", Join([]interface{}{1, "", true, 3.14, "foo", nil}, ",")) // and best-effort with weird types assert.Equal(t, "[foo],bar", Join([]interface{}{[]string{"foo"}, "bar"}, ",")) |
