反射常用操作示例
判断 Struct 是否实现了指定的 Interface
type I interface {
Foo()
Bar()
}
type S struct {}
func (*S) Foo() {
fmt.Println("foo")
}
func (*S) Bar() {
fmt.Println("bar")
}
func main() {
iType := reflect.TypeOf((*I)(nil)).Elem()
fmt.Println(reflect.TypeOf(S{}).Implements(iType)) // output: false
fmt.Println(reflect.TypeOf(&S{}).Implements(iType)) // output: true
}
反射调用 Struct 的指定方法
type S struct{}
func (*S) Hello() {
fmt.Println("hello world")
}
func main() {
ref := reflect.New(reflect.TypeOf(S{}))
method := ref.MethodByName("Hello")
if method.IsValid() {
method.Call(nil)
}
}
通过函数签名动态调用函数
// foo sum of nums
func foo(nums ...int) int {
var sum int
for _, num := range nums {
sum += num
}
return sum
}
// println string
func bar(s string) {
fmt.Println(s)
}
func exec(call interface{}, args ...interface{}) ([]reflect.Value, error) {
f := reflect.ValueOf(call)
if f.Kind() != reflect.Func {
return nil, errors.New("call must be func")
}
n := len(args)
params := make([]reflect.Value, n)
for i := 0; i < n; i++ {
params[i] = reflect.ValueOf(args[i])
}
return f.Call(params), nil
}
func main() {
// foo(1, 2, 3, 4, 5) return 15
res, _ := exec(foo, 1, 2, 3, 4, 5)
fmt.Println(res[0].Int()) // 15
// bar("hello world")
_, _ = exec(bar, "hello world")
}
通过 Tag 修改对应字段的默认值
type T struct {
X int `default:"10"`
S string `default:"hello"`
B bool `default:"true"`
}
func (t T) String() string {
return fmt.Sprintf("[ %v, %v, %v ] ", t.X, t.S, t.B)
}
func setDefault(tag string, value reflect.Value, field reflect.StructField) {
// 获取 tag 内容
df := field.Tag.Get(tag)
// 判断是否可改(私有属性无法设置)
if value.CanSet() {
// 根据类型修改为不同的值
switch field.Type.Kind() {
case reflect.String:
value.SetString(df)
case reflect.Int:
i, err := strconv.Atoi(df)
if err != nil {
value.SetInt(0)
} else {
value.SetInt(int64(i))
}
case reflect.Bool:
value.SetBool(df == "true")
case reflect.Float64:
i, err := strconv.Atoi(df)
if err != nil {
value.SetFloat(0)
} else {
value.SetFloat(float64(i))
}
default:
}
}
}
func main() {
t := T{}
fmt.Println(t) // output: [ 0, , false ]
// 反射设置默认值
tt := reflect.TypeOf(t)
vt := reflect.ValueOf(&t)
for i := 0; i < tt.NumField(); i++ {
field := tt.Field(i)
value := vt.Elem().Field(i)
setDefault("default", value, field)
}
fmt.Println(t) // output: [ 10, hello, true ]
}
参考文档