首页 > 技术文章 > Go语言轻量级框架-Gin与入门小案例MySQL增删查改

xwxz 2020-08-19 21:35 原文

Go语言轻量级框架-Gin与入门小案例MySQL增删查改

简单的使用一下gin框架,然后使用它完成数据库的增删查改

一、安装和开始

要想使用gin必须要下载和安装它,切换到自己的工作空间,执行go命令

go get -u github.com/gin-gonic/gin

但是因为网络问题可能会失败,实在不行就直接通过github下载也可以。
安装好之后就可以直接使用了,打开ide创建一个新的项目helloGin,创建main.go

package main

import (
	"github.com/gin-gonic/gin"
	"log"
)

func main() {
	// Engin
	router := gin.Default()
	//router := gin.New()
	
	router.GET("/hello", func(context *gin.Context) {
		log.Println(">>>> hello gin start <<<<")
		context.JSON(200, gin.H{
			"code":    200,
			"success": true,
			"data" : "Hello LXR!",
		})
	})
	// 指定地址和端口号
	router.Run("127.0.0.1:8082")
}

在main函数里面首先通过调用gin.Default()函数返回的是一个Engin指针,Engin代表的是整个框架的一个实例,它包含了多路复用、中间件和配置的设置,其实就是封装了我们需要的内容。一般创建Engin都是使用Default()或者New(),当然Default()本身内部也是调用的New()函数。
接着调用Engin的GET方法,这个方法两个参数,一个是相对路径,一个是多个handler,即针对用户一个请求地址,我可以指定多个handler来处理用户请求。但是一般情况下我们都是一个handler处理一个请求。上面的代码里使用了一个匿名函数处理"/hello"请求。然后以JSON格式的数据响应用户请求,这个方法有两个参数,第一个是状态,第二个是结果。我这里直接指定200,表示成功,或者也可以用http包的常量值http.StatusOK;gin.H其实是一个map的数据结构,然后将其转成json格式输出。
最后是router.Run("localhost:8082"),这个方法是指定服务的主机和端口号,不过一般直接指定端口号就行了。
下面启动项目,并访问"localhost:8082/hello",访问结果如下图所示:

二、一个简单的gin与MySQL数据库交互

也是基于MVC的编程思想,所以将代码分成了controller和model还有dao主要代码,目录结构如下

首先需要去mysql里面创建一个数据库,SQL文件如下

CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID ',
  `username` varchar(64) NOT NULL COMMENT '用户名称 ',
  `age` int(11) NOT NULL COMMENT 'ID ',
  `mobile` varchar(64) NOT NULL COMMENT '手机号码 ',
  `sex` varchar(32) DEFAULT NULL COMMENT '性别 ',
  `address` varchar(64) DEFAULT NULL COMMENT '地址 ',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';

model里面其实数据库表的一个类,go语言就是一个结构体

User.go

package model

type User struct {
	Username 	string	`json:"name" form:"name"`
	Age  		uint8	`json:"age" form:"age"`
	Mobile 		string	`json:"mobile" form:"mobile"`
	Sex			string	`json:"sex" form:"sex"`
	Address 	string	`json:"address" form:"address"`
	Id          uint16  `json:"id" form:"id"`
}


main函数其实相当于Java里面的controller 处理路由的,代码如下

main.go

package main

import (
	"github.com/gin-gonic/gin"
	"github.com/helloGin/controller"
	"net/http"
)

func main()  {

	// Engin
	router := gin.Default()

	//router := gin.New()
	router.LoadHTMLGlob("template/*")
	router.GET("/hello", hello)

	// 路由组
	user := router.Group("/user")
	{	// 请求参数在请求路径上
		user.GET("/get/:id/:username",controller.QueryById)
		user.GET("/query",controller.QueryParam)
		user.POST("/insert",controller.InsertNewUser)
		user.GET("/form",controller.RenderForm)
		user.POST("/form/post",controller.PostForm)
		//可以自己添加其他,一个请求的路径对应一个函数

		// ...
	}

	file := router.Group("/file")
	{
		// 跳转上传文件页面
		file.GET("/view",controller.RenderView)
		// 根据表单上传
		file.POST("/insert",controller.FormUpload)
		file.POST("/multiUpload",controller.MultiUpload)
		// base64上传
		file.POST("/upload",controller.Base64Upload)
	}

	// 指定地址和端口号
	router.Run(":9090")
}

func hello(context *gin.Context) {
	println(">>>> hello function start <<<<")

	context.JSON(http.StatusOK,gin.H{
		"code":200,
		"success":true,
	})
}

UserController.go

package controller

import (
	"database/sql"
	"github.com/gin-gonic/gin"
	"github.com/helloGin/database"
	"github.com/helloGin/model"
	"log"
	"net/http"

)

var db *sql.DB

func init()  {
	log.Println(">>>> get database connection start <<<<")
	db = database.GetDataBase()
}

// localhost:9090/user/query?id=2&name=hello
func QueryParam(context *gin.Context) {
	println(">>>> query user by url params action start <<<<")
	id := context.Query("id")
	name := context.Request.URL.Query().Get("name")
	var u model.User
	context.Bind(&u)
	context.ShouldBind(&u)

	println(u.Username)
	rows := db.QueryRow("select username,address,age,mobile,sex from t_user where id = ? and username = ?",id,name)
	var user model.User
	err := rows.Scan(&user.Username,&user.Address,&user.Age,&user.Mobile,&user.Sex)
	checkError(err)

	checkError(err)
	context.JSON(200,gin.H{
		"result":user,
	})

}
// localhost:9090/user/get/2/hello
func QueryById (context *gin.Context) {
	println(">>>> get user by id and name action start <<<<")

	// 获取请求参数
	id := context.Param("id")
	name := context.Param("username")

	// 查询数据库
	rows := db.QueryRow("select username,address,age,mobile,sex from t_user where id = ? and username = ?",id,name)

	var user model.User
	//var username string
	//var address string
	//var age uint8
	//var mobile string
	//var sex string
	err := rows.Scan(&user.Username,&user.Address,&user.Age,&user.Mobile,&user.Sex)
	checkError(err)

	checkError(err)
	context.JSON(200,gin.H{
		"result":user,
	})
}

// json格式数据
func InsertNewUser (context *gin.Context) {
	println(">>>> insert controller action start <<<<")
	var user model.User

	// 使用ioutile读取二进制数据
	//bytes,err := ioutil.ReadAll(context.Request.Body)
	//if err != nil {
	//	log.Fatal(err)
	//}
	//err = json.Unmarshal(bytes,&user)

	// 直接将结构体和提交的json参数作绑定
	err := context.ShouldBindJSON(&user)

	// 写入数据库
	res,err := db.Exec("insert into t_user (username,sex,address,mobile,age) values (?,?,?,?,?)",
		&user.Username,&user.Sex,&user.Address,&user.Mobile,&user.Age)
	var count int64
	count,err = res.RowsAffected()
	checkError(err)
	if count != 1 {
		context.JSON(200,gin.H{
			"success":false,
		})
	} else {
		context.JSON(200,gin.H{
			"success":true,
		})
	}

}

// form表单提交
func PostForm(context *gin.Context) {
	println(">>>> bind form post params action start <<<<")
	var u model.User

	// 绑定参数到结构体
	context.Bind(&u)
	context.ShouldBind(&u)
	res,err := db.Exec("insert into t_user (username,sex,address,mobile,age) values (?,?,?,?,?)",
		&u.Username,&u.Sex,&u.Address,&u.Mobile,&u.Age)
	var count int64
	count,err = res.RowsAffected()
	checkError(err)

	if count != 1 {
		context.JSON(200,gin.H{
			"success":false,
		})
	} else {
		//context.JSON(200,gin.H{
		//	"success":true,
		//})

		// 重定向
		context.Redirect(http.StatusMovedPermanently,"/file/view")
	}

}

// 跳转html
func RenderForm(context *gin.Context) {
	println(">>>> render to html action start <<<<")

	context.Header("Content-Type", "text/html; charset=utf-8")
	context.HTML(200,"insertUser.html",gin.H{})
}

func checkError(e error) {
	if e != nil {
		log.Fatal(e)
	}
}

MySQL的配置文件代码如下

connectDB.go

package database

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"log"
	"strings"
)

//数据库的基础信息
const (
	userName = "root"
	password = "xxw2020"
	ip = "127.0.0.1"
	port = "3306"
	dbName = "student"
)

func GetDataBase() *sql.DB {

	//mysql 数据库
	//构建连接:"用户名:密码@tcp(IP:端口)/数据库?charset=utf8"
	path := strings.Join([]string{userName, ":", password, "@tcp(",ip, ":", port, ")/", dbName, "?charset=utf8"}, "")
	fmt.Println(path)
	//打开数据库,前者是驱动名,所以要导入: _ "github.com/go-sql-driver/mysql"
	DB, _ := sql.Open("mysql", path)
	if DB == nil {
		log.Fatal("连接失败!")
		return nil
	}
	//设置数据库最大连接数
	DB.SetConnMaxLifetime(10)
	//设置上数据库最大闲置连接数
	DB.SetMaxIdleConns(5)
	//验证连接
	if err := DB.Ping(); err != nil{
		log.Fatal("opon database fail")
		return nil
	}
	return DB
}

主要的代码已经上传到github

首先这个需要在gopath目录下的src/github.com/目录下clone该代码,然后运行数据库建表,最后执行就ok了

参考博客golang轻量级框架-Gin入门

推荐阅读