使用go搭建个人博客(二):数据库和路由

3,674 阅读5分钟

  上一篇文章简单介绍了选择的技术栈和怎么初始化一个Web项目,项目目录等,这篇就来介绍路由的配置和怎么连接数据库、使用xorm

路由配置

  上一章介绍了使用gin创建一个初始的web项目。现在,我们就使用gin提供的路由机制来配置。在main.go中进行添加:

main.go:

package main

import (
    "io"
    "os"

    "github.com/gin-gonic/gin"
    "github.com/zachrey/blog/routers"
)

func main() {
    r := gin.New()

    // 设置日志文件
    f, _ := os.Create("gin.log")
    gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
    // 使用日志中间件
    r.Use(gin.Logger())
    // 设置静态文件夹
    r.Static("/static", "./static")
    // 加载路由
    routers.LoadRouters(r)
    r.Run(":8888")
}

routers.LoadRouters函数,我们放在routers/包下面,让所有的路由都统一管理:

routers/router.go:

package routers

import (
    "log"
    "net/http"

    "github.com/gin-gonic/gin"
    // ctrs "github.com/zachrey/blog/controllers"
)

// LoadRouters 初始化router
func LoadRouters(router *gin.Engine) {
    loadRouters(router)
}

func loadRouters(router *gin.Engine) {
    // 这里测试根路由
    /*
        控制器函数会接收一个`gin.Context`类型的指针,这个指针包含http的请求和响应信息和操作方法。
    */
    router.GET("/", func(c *gin.Context) {
        post := models.GetPostByID(1)
        log.Println("@@ post", post)
        // 返回一个json格式的数据
        c.JSON(http.StatusOK, gin.H{
            "Status": 0,
            "data":   post,
        })
    })
    // 路由控制函数,我们全部放在controllers目录下
    //router.GET("/get-posts", ctrs.GetPosts)

    // ......  很多很多路由。。。
}

ctrs.GetPosts这个控制器函数,之后结合数据库来进行演示。现在启动项目go run main.go,然后在浏览器中访问localhost:8888/来看,根路由会返回什么。

连接数据库

  由于个人博客功能不是很复杂,这里就直接使用了sqlite这种轻量级的数据库。GO没有内置的数据库驱动,但是GO定义了数据库驱动包接口database/sql/driver,所以就算对于不同的数据库,可以在这些接口的基础上来开发自己的驱动包。那么,需要连接sqlite数据库,我们就需要去找sqlite的数据驱动包。

github.com/mattn/go-sqlite3

以上就是需要用到的驱动包的地址,只需要在项目中导入初始化就行。

其他的驱动包列表:github.com/golang/go/w…

在项目的入口文件main.go初始化(导入)数据库驱动:

main.go:

package main

import (
    "io"
    "os"

    "github.com/gin-gonic/gin"
    _ "github.com/mattn/go-sqlite3" // 只导入,并不需要去使用,所以注意前面的"_"下划线
)

func main() {
    r := gin.New()
    ...
    r.Run(":8888")
}

初始化数据库后,在database目录下,创建一个数据库配置文件,我们使用xorm来连接数据库。

database/sqlite3.go:

package database

import (
    "log"

    "github.com/xormplus/xorm" // 记得 go get 获取哦
)
// ORM xorm引擎的实例,供其他模块可以直接使用,注意**首字母大写**,因为`Go`语音的隐藏和公开的规则,大写为公开,小写为隐藏。
var ORM *xorm.Engine

func init() { // 使用init来自动连接数据库,并创建ORM实例
    var err error
    ORM, err = xorm.NewEngine("sqlite3", "./database/test.db")
    if err != nil {
        log.Fatalln(err)
        return
    }
    err = ORM.Ping() // 测试能操作数据库
    if err != nil {
        log.Fatalln(err)
        return
    }
    ORM.ShowSQL(true) // 测试环境,显示每次执行的sql语句长什么样子
}

上面的xorm操作,建议多看官方文档。我的github上有现成的测试的数据库文件,也就是这个博客系统的数据库文件,大家可以下载下来,连接试试。看会不会报错,ping操作能不能连通。这里有个注意的地方./database/test.db,这个相对路径,因为我把test.db这个文件放在sqlite3.go这个配置文件的同级目录下,如果你创建引擎的时候这样写./test.db,它并不会指向/database/test.db这个文件,而是会指向项目根目录下的/test.db,从而会创建一个新的空的/text.db文件。因为Go语言是已包来管理项目的,所以./表示的是包的同级目录,而不是包里面文件的同级目录。

创建ORM模板

  所有的模板都放在models下面,每一个model都对应一张数据库的表,我们可以使用sqlite数据库连接工具来看看,test.db有哪些表和具体字段,这里就展示model了,因为字段都是对应的。

models/post.go:

package models

import (
    "log"

    db "github.com/zachrey/blog/database" // 导入之前创建的数据库引擎实例,用来操作数据库
)

type MPost struct {
    Id         int64  `xorm:"pk autoincr"`
    Title      string `xorm:"'title'"`
    FileName   string `xorm:"file_name"`
    TextAmount int64  `xorm:"text_amount"`
    CreateTime int64  `xorm:"created 'create_time'"`
}

// GetPostByID 根据ID获取文章
func GetPostByID(Id int64) *MPost {
    var post MPost
    // 根据Id得到一个MPost类型的实例
    has, err := db.ORM.Table("posts").Id(Id).Get(&post)
    if err != nil {
        log.Println("ERROR:", err)
        return nil
    }
    if has == false {
    return nil
    }
    return &post
}

// GetPosts 获取所有的文章
func GetPosts() *[]MPost {
    var post []MPost
    err := db.ORM.Table("posts").Find(&post)
    if err != nil {
        log.Println("ERROR:", err)
        return nil
    }
    return &post
}

使用struct来对应数据库的表,表中字段的类型,约束等。注意结构体的属性首字母都是大写的,视情况而定,如果这个结构体需要被访问,最好全部都写错大写。关于类型的映射,可以看官网的“Go与字段类型对应表”目录,里面会有详细的说明。对于xorm:"pk autoincr"这样的东西,成为Tag,具体的Tag规则看官网的“Column属性定义”目录的介绍。

在控制器中使用模板上的方法

控制器全部放在controllers/下。

/controllers/posts.go:

package controllers

import (
    "log"
    "net/http"

    "github.com/gin-gonic/gin"
    "github.com/zachrey/blog/models"
)

//GetPosts 获取所有的文章
func GetPosts(c *gin.Context) {
    labels := models.GetPosts() // 使用在模板中书写的方法
    c.JSON(http.StatusOK, gin.H{
        "status": 0,
        "data":   labels,
    })
}

在路由中使用控制器

routers/router.go:

package routers

import (
    "log"
    "net/http"

    "github.com/gin-gonic/gin"
    ctrs "github.com/zachrey/blog/controllers"
)

// LoadRouters 初始化router
func LoadRouters(router *gin.Engine) {
    loadRouters(router)
}

func loadRouters(router *gin.Engine) {
    // 这里测试根路由
    /*
        控制器函数会接收一个`gin.Context`类型的指针,这个指针包含http的请求和响应信息和操作方法。
    */
    router.GET("/", func(c *gin.Context) {
        post := models.GetPostByID(1)
        log.Println("@@ post", post)
        // 返回一个json格式的数据
        c.JSON(http.StatusOK, gin.H{
            "Status": 0,
            "data":   post,
        })
    })
    // 路由控制函数,我们全部放在controllers目录下
    router.GET("/get-posts", ctrs.GetPosts)

    // ......  很多很多路由。。。
}

现在我们来访问localhost:8888/get-posts,查看返回的json数组。

最后

  该项目示例已经写完放在github上了,这第二篇,用来介绍配置路由和使用xorm操作数据库。欢迎讨论或者留言,也可以在我的github上克隆项目直接跑着看看。之后继续更新,中间遇到的问题和一些解决办法。