golang reflect包实现了反射。动态的获得程序运行时对象的结构和信息。
reflect 包中提供了两个基础的关于反射的函数来获取上述的接口和结构体:
func TypeOf(i interface{}) Type
func ValueOf(i interface{}) Value
大体上可以这样理解,TypeOf获取对象的类型信息,ValueOf获取对象中存储的值。
golang tag
golang中可以为结构体的字段添加tag。golang本身的encoding/json包解析json使用了tag,一些开源的orm框架如gorm,也使用了tag。tag可以方便的为结构体的字段添加一些信息,用reflect可以读取到,加以利用。
这是一个用tag标记列名以实现结构体自动生成xlsx的例子:
```
type Employee struct{
ID int `xlsx:”工号”`
Name string `xlsx:”姓名”`
Email string `xlsx:”邮箱”`
}
func Outputxlsx(es []*Employee) ([]byte, error) {
xt := reflect.TypeOf(es[0])
xv := reflect.ValueOf(es[0])
rows := [][]interface{}{}
headers := []interface{}{}
for i := 0i <xt.Elem().NumField()i++ {
head, ok := xt.Elem().Field(i).Tag.Lookup("xlsx")
if ok {
headers = append(headers, head)
}
}
for _, e := range es {
cells := []interface{}{}
xv := reflect.ValueOf(e)
for i := 0i <xv.Elem().NumField()i++ {
_, ok := xt.Elem().Field(i).Tag.Lookup("xlsx")
if ok {
cells = append(cells, xv.Elem().Field(i).Interface())
}
}
rows = append(rows, cells)
}
file := xlsx.NewFile()
sheet, _ := file.AddSheet("sheet1")
row := sheet.AddRow()
for _, header := range headers {
row.AddCell().Value = fmt.Sprintf("%v", header)
}
for _, v := range rows {
row := sheet.AddRow()
for _, vv := range v {
row.AddCell().Value = fmt.Sprintf("%v", vv)
}
}
var buffer bytes.Buffer
if err := file.Write(&buffer)err != nil {
return nil, err
}
return buffer.Bytes(), nil
}
```
package daoimport (
_ "code.google.com/p/go-mysql-driver/mysql"
//接口实现,_表示不调用实现,调用接口。
"database/sql"
"fmt"
)
func GetConn() *sql.DB {
//配置数据库连接地址.统一配置.
db, _ := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/test")
fmt.Println(db)
return db
}
//使用的时候
db := dao.GetConn()
defer db.Close()
//开始事物
tx, _ := db.Begin()
//查询数据:
// func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error)
select_sql := " SELECT id,user_id,create_date,title FROM post WHERE id = ? "
row := tx.QueryRow(select_sql, id)
//查询userId,创建时间标题信息.
if row != nil {
row.Scan(&Id, &UserId, &CreateDate, &Title)
}