github.com/tencent/goom@v1.0.1/var.go (about) 1 package mocker 2 3 import ( 4 "fmt" 5 "reflect" 6 7 "github.com/tencent/goom/internal/logger" 8 ) 9 10 // VarMock 变量 mock 11 // 支持全局变量, 任意类型包括不限于基本类型,结构体,函数变量,指针与非指针类型 12 // 主要提供方便变量 mock/reset 场景的能力支持 13 type VarMock interface { 14 Mocker 15 // Set 设置变量值, val 类型必须和变量指针指向的值的类型一致 16 Set(val interface{}) 17 } 18 19 // defaultVarMocker 默认变量 mock 实现 20 type defaultVarMocker struct { 21 target interface{} 22 mockValue interface{} 23 originValue interface{} 24 canceled bool // canceled 是否被取消 25 } 26 27 // String mock 的名称或描述, 方便调试和问题排查 28 func (m *defaultVarMocker) String() string { 29 return fmt.Sprintf("var at[%d]", reflect.ValueOf(m.target).Pointer()) 30 } 31 32 // NewVarMocker 创建 VarMock 33 func NewVarMocker(target interface{}) VarMock { 34 t := reflect.ValueOf(target) 35 if t.Type().Kind() != reflect.Ptr { 36 panic("VarMock target must be a pointer.") 37 } 38 return &defaultVarMocker{ 39 target: target, 40 canceled: false, 41 } 42 } 43 44 // Apply 变量取值回调函数, 只会执行一次 45 // 注意: Apply 会覆盖之前设定 Set 的值 46 func (m *defaultVarMocker) Apply(callback interface{}) { 47 f := reflect.ValueOf(callback) 48 if f.Kind() != reflect.Func { 49 panic("VarMock Apply argument(callback) must be a func.") 50 } 51 ret := f.Call([]reflect.Value{}) 52 if ret == nil || len(ret) != 1 { 53 panic("VarMock Apply callback's returns length must be 1.") 54 } 55 56 m.doSet(ret[0].Interface()) 57 logger.Consolefc(logger.DebugLevel, "mocker [%s] apply.", logger.Caller(5), m.String()) 58 } 59 60 // Cancel 取消 mock 61 func (m *defaultVarMocker) Cancel() { 62 t := reflect.ValueOf(m.target) 63 t.Elem().Set(reflect.ValueOf(m.originValue)) 64 m.canceled = true 65 } 66 67 // Canceled 是否取消了 mock 68 func (m *defaultVarMocker) Canceled() bool { 69 return m.canceled 70 } 71 72 // Set 设置变量值 73 // 注意: Set 会覆盖之前设定 Apply 的值 74 func (m *defaultVarMocker) Set(value interface{}) { 75 m.doSet(value) 76 logger.Consolefc(logger.DebugLevel, "mocker [%s] apply.", logger.Caller(5), m.String()) 77 } 78 79 func (m *defaultVarMocker) doSet(value interface{}) { 80 t := reflect.ValueOf(m.target) 81 m.originValue = t.Elem().Interface() 82 d := reflect.ValueOf(value) 83 t.Elem().Set(d) 84 m.mockValue = value 85 }