feat: support env tag in config (#2577)
* feat: support env tag in config * chore: add more tests * chore: add more tests, add stringx.Join * fix: test fail * chore: remove print code * chore: rename variable
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
package lang
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Placeholder is a placeholder object that can be used globally.
|
||||
var Placeholder PlaceholderType
|
||||
|
||||
@@ -9,3 +15,64 @@ type (
|
||||
// PlaceholderType represents a placeholder type.
|
||||
PlaceholderType = struct{}
|
||||
)
|
||||
|
||||
// Repr returns the string representation of v.
|
||||
func Repr(v interface{}) string {
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
// if func (v *Type) String() string, we can't use Elem()
|
||||
switch vt := v.(type) {
|
||||
case fmt.Stringer:
|
||||
return vt.String()
|
||||
}
|
||||
|
||||
val := reflect.ValueOf(v)
|
||||
if val.Kind() == reflect.Ptr && !val.IsNil() {
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
return reprOfValue(val)
|
||||
}
|
||||
|
||||
func reprOfValue(val reflect.Value) string {
|
||||
switch vt := val.Interface().(type) {
|
||||
case bool:
|
||||
return strconv.FormatBool(vt)
|
||||
case error:
|
||||
return vt.Error()
|
||||
case float32:
|
||||
return strconv.FormatFloat(float64(vt), 'f', -1, 32)
|
||||
case float64:
|
||||
return strconv.FormatFloat(vt, 'f', -1, 64)
|
||||
case fmt.Stringer:
|
||||
return vt.String()
|
||||
case int:
|
||||
return strconv.Itoa(vt)
|
||||
case int8:
|
||||
return strconv.Itoa(int(vt))
|
||||
case int16:
|
||||
return strconv.Itoa(int(vt))
|
||||
case int32:
|
||||
return strconv.Itoa(int(vt))
|
||||
case int64:
|
||||
return strconv.FormatInt(vt, 10)
|
||||
case string:
|
||||
return vt
|
||||
case uint:
|
||||
return strconv.FormatUint(uint64(vt), 10)
|
||||
case uint8:
|
||||
return strconv.FormatUint(uint64(vt), 10)
|
||||
case uint16:
|
||||
return strconv.FormatUint(uint64(vt), 10)
|
||||
case uint32:
|
||||
return strconv.FormatUint(uint64(vt), 10)
|
||||
case uint64:
|
||||
return strconv.FormatUint(vt, 10)
|
||||
case []byte:
|
||||
return string(vt)
|
||||
default:
|
||||
return fmt.Sprint(val.Interface())
|
||||
}
|
||||
}
|
||||
|
||||
131
core/lang/lang_test.go
Normal file
131
core/lang/lang_test.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package lang
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRepr(t *testing.T) {
|
||||
var (
|
||||
f32 float32 = 1.1
|
||||
f64 = 2.2
|
||||
i8 int8 = 1
|
||||
i16 int16 = 2
|
||||
i32 int32 = 3
|
||||
i64 int64 = 4
|
||||
u8 uint8 = 5
|
||||
u16 uint16 = 6
|
||||
u32 uint32 = 7
|
||||
u64 uint64 = 8
|
||||
)
|
||||
tests := []struct {
|
||||
v interface{}
|
||||
expect string
|
||||
}{
|
||||
{
|
||||
nil,
|
||||
"",
|
||||
},
|
||||
{
|
||||
mockStringable{},
|
||||
"mocked",
|
||||
},
|
||||
{
|
||||
new(mockStringable),
|
||||
"mocked",
|
||||
},
|
||||
{
|
||||
newMockPtr(),
|
||||
"mockptr",
|
||||
},
|
||||
{
|
||||
&mockOpacity{
|
||||
val: 1,
|
||||
},
|
||||
"{1}",
|
||||
},
|
||||
{
|
||||
true,
|
||||
"true",
|
||||
},
|
||||
{
|
||||
false,
|
||||
"false",
|
||||
},
|
||||
{
|
||||
f32,
|
||||
"1.1",
|
||||
},
|
||||
{
|
||||
f64,
|
||||
"2.2",
|
||||
},
|
||||
{
|
||||
i8,
|
||||
"1",
|
||||
},
|
||||
{
|
||||
i16,
|
||||
"2",
|
||||
},
|
||||
{
|
||||
i32,
|
||||
"3",
|
||||
},
|
||||
{
|
||||
i64,
|
||||
"4",
|
||||
},
|
||||
{
|
||||
u8,
|
||||
"5",
|
||||
},
|
||||
{
|
||||
u16,
|
||||
"6",
|
||||
},
|
||||
{
|
||||
u32,
|
||||
"7",
|
||||
},
|
||||
{
|
||||
u64,
|
||||
"8",
|
||||
},
|
||||
{
|
||||
[]byte(`abcd`),
|
||||
"abcd",
|
||||
},
|
||||
{
|
||||
mockOpacity{val: 1},
|
||||
"{1}",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.expect, func(t *testing.T) {
|
||||
assert.Equal(t, test.expect, Repr(test.v))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type mockStringable struct{}
|
||||
|
||||
func (m mockStringable) String() string {
|
||||
return "mocked"
|
||||
}
|
||||
|
||||
type mockPtr struct{}
|
||||
|
||||
func newMockPtr() *mockPtr {
|
||||
return new(mockPtr)
|
||||
}
|
||||
|
||||
func (m *mockPtr) String() string {
|
||||
return "mockptr"
|
||||
}
|
||||
|
||||
type mockOpacity struct {
|
||||
val int
|
||||
}
|
||||
Reference in New Issue
Block a user