golang的接口类型是golang的一大神器,下面我们来看看如何将接口类型转换成其他的类型
package tests
import (
"fmt"
"github.com/go-xorm/core"
"github.com/go-xorm/xorm"
_ "github.com/lunny/godbc"
"os"
"testing"
"zks.com/business/module"
)
var DBE *xorm.Engine
func Test_InitDb(t *testing.T) {
dbhost := "localhost\\MSSQLSERVER2008"
dbname := "FoodSafety_KF"
dbuser := "sa"
dbpwd := "sasa"
var err error
DBE, err = xorm.NewEngine("odbc", fmt.Sprintf("driver=SQL Server;server=%s;database=%s; uid=%s; pwd=%s;",
dbhost, dbname, dbuser, dbpwd))
if err != nil {
fmt.Println("failed to initialize database")
os.Exit(2)
}
DBE.SetMapper(core.SameMapper{})
DBE.ShowDebug = true
DBE.ShowErr = true
DBE.ShowSQL = true
}
func Test_Something(t *testing.T) {
list := new([]module.Base_Module)
getdata(list)
}
func getdata(data interface{}) {
DBE.Limit(3).Find(data)
if m, ok := data.(*[]module.Base_Module); ok{
d := *m
for i := 0; i < len(d); i++ {
fmt.Println(d[i].Fullname)
}
}
}
在上面的代码中,我new了一个结构体数组,然后把指向这个结构体数组的指针作为参数发送给了getdata这个函数,而getdata这个函数在接收这个参数时用了interface{}来接收,那么就是说指针被转化成了接口类型。
如果我们去掉m, ok := data.(*[]module.Base_Module)这句话的话,程序是会报错的。因为接口类型不能取索引,而且也没有Fullname这个字段。
上面那句话的作用就是把接口类型转化成指向[]module.Base_Module的指针,m是接口被转化之后的值,ok是用来标识转换有没有成功。这种转换在golang中就叫做golang的类型断言。
在转换成功后,我又对转换后的值m做了一个取值的操作,这样就可以取到指针指向的地址的值。之后就可以像操作一般结构体数组那样来操作d这个变量了。
如果我们不知道这个data这个参数的类型,但是我们知道要取哪个字段的值,那应该怎么取呢?
答案是:用反射来取,看下面的代码:
func getdata(data interface{}) {
DBE.Limit(3).Find(data)
m := reflect.ValueOf(data).Elem()
for i := 0; i < m.Len(); i++ {
fmt.Println(m.Index(i).FieldByName("Fullname"))
}
}
把getdataz这个函数改成这样,得到的结果和上面的代码是一样的。对于上面的反射,我们需要注意一点,一定要在reflect.ValueOf(data)后面加上Elem(),不然的话会报错。Elem这个函数的作用就是取得指针指向的地址的值,相当于*操作符。那么如果传过来的参数不是一个指针,而是一个实体,那么就不要用Elem()这个函数了。