golang类型断言

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()这个函数了。

你可能感兴趣的:(golang类型断言)