反射的简单使用
ValueOf, Elem,Indirect
- reflect.ValueOf把一个interface{}包起来成为reflect.Value
- Value.Interface() 是反向操作,得到被Value包起来的值
- Value.Elem 和 reflect.Indirect类似,当Value包起来一个指针时,这两个方法可以得到指针指向的具体对象的值
var i int = 3
var p *int = &i
fmt.Println(p, i) //0xc0000ae008 3
v := reflect.ValueOf(p)
fmt.Println(v.Interface()) // This is the p pointer, 0xc0000ae008
v2 := v.Elem()
fmt.Println(v2.Interface()) // This is i's value: 3
v3 := reflect.Indirect(v)
fmt.Println(v3.Interface()) // This is i's value: 3
v4 := reflect.ValueOf(i)
fmt.Println(v4.Interface()) // This is i's value: 3
- (reflect.Type).Name() 返回类型名
- (reflect.Type).Field(i) 获取第i个成员变量
func(Type) Elem() Type的作用
就像是一层层剥开,取出当前type内部元素的type,如果不能再剥,会panic
type Account struct {
Username string
Password string
}
v := reflect.ValueOf([]*Account{&Account{}})
fmt.Println(v.Type()) //[]*main.Account
fmt.Println(v.Type().Elem()) //*main.Account
fmt.Println(v.Type().Elem().Elem()) //main.Account
fmt.Println(v.Type().Elem().Elem().Elem()) //panic,elem of invalid type
day1
engine、session、log
连接数据库,原生操作的封装
engine中链接db,用*sql.db创建session并复用,session中执行sql操作。
关于TestMain
- 普通的test case,会调用TestMain,用来做测试前后额外的工作
- 在 TestMain 函数的最后,应该使用 m.Run 的返回值作为参数去调用 os.Exit。
func TestMain(m *testing.M) {
setup()
code := m.Run()
shutdown()
os.Exit(code)
}
day3
session.Find函数中,反射的使用。
type User struct {
Name string
Age int
}
func main() {
users := make([]User, 0)
destSlice := reflect.Indirect(reflect.ValueOf(&users)) //[]User
// dest := User{"Tom", 18}
// destSlice.Set(reflect.Append(destSlice, reflect.ValueOf(dest)))
//这里已经可以验证destSlice的修改相当于对user赋值
destType := destSlice.Type().Elem() //type User{}
dest := reflect.New(destType).Elem() //Value User{}
field1 := dest.FieldByName("Name").Addr().Interface() //获取指向Name字段的指针
// 模拟rows.Scan对field1赋值
field1Str, _ := field1.(*string)
*field1Str = "Angel"
destSlice.Set(reflect.Append(destSlice, dest))
_, _ = pretty.Println(users)
}
- 传入&Users再使用reflect,可以对原始值赋值(类似指针)参考如何用reflect对struct赋值
- 建立实际类型为User的reflect.Value dest,通过指向字段的指针对其赋值