最近写到一个程序,是关于go获取数据库的内容。按照以往用java的经验,我都是可以直接使用orm的,很方便快捷。go也有第三方的orm库,但是我嫌麻烦不想用。

问题很简单:我需要从数据库里面获取出来数据之后,封装成我需要的数据结构。在实施的时候遇到了一些问题。

数据结构

假设我需要获取的这个数据结构

type Article struct {
    Cid          int    `json:"cid"`
    Title        string `json:"title"`
    Slug         string `json:"slug"`
    Created      int    `json:"created"`
    Modified     int    `json:"modified"`
    Text         string `json:"text"`
    Order        int    `json:"order"`
    AuthorId     int    `json:"author_id"`
    Template     string `json:"template"`
    ArticleType  string `json:"article_type"`
    Status       string `json:"status"`
    Password     string `json:"password"`
    CommentSum   int    `json:"comment_sum"`
    AllowComment bool   `json:"allow_comment"`
    AllowPing    bool   `json:"allow_ping"`
    AllowFeed    bool   `json:"allow_feed"`
    Parent       int    `json:"parent"`
}

我所做的就是传递类型,然后从数据库提取出来数据,反射构造变量,完成!
但是,根据go默认的定义,变量和函数如果是小写的话,会被认为私有成员,无法反射。
所以,我的struct里面的成员全部都是大写开头。

数据库提取

这块问题不大,go已经有了mysql的驱动,我们直接使用就好了。

db, err := sql.Open("mysql", "root:123456@/typecho?charset=utf8")
if err != nil {
    panic(err)
}
defer db.Close()
stmt, err := db.Prepare(query)
if err != nil {
    panic(err)
}
defer stmt.Close()
rows, err := stmt.Query()
if err != nil {
    panic(err)
}
defer rows.Close()

变量反射

这一块是个难点,也是我们这篇文章的核心。
我们所做的是需要获取struct里面的value,然后依次获取里面的变量类型,使用数据库函数写入。

result := make([]interface{}, 0)
s := reflect.ValueOf(struc).Elem()
leng := s.NumField()
onerow := make([]interface{}, leng)
for i := 0; i < leng; i++ {
    onerow[i] = s.Field(i).Addr().Interface()
}
for rows.Next() {
    rows.Scan(onerow...)
    result = append(result, s.Interface())
}

正常情况下,我们应该这么写

err:=rows.Scan(onerow...)
if err != nil {
    panic(err)
}

但是,如果数据库里面是空的话,err一定不为空的。如果我们不检测,反正数据赋值没有错误,就不加了!

go 数据库 反射

已有 2 条评论
  1. 小斌

    来踩踩贵站!

    小斌 回复
    1. hundred

      谢谢访问!已回访

      hundred 回复
发表新评论