ginapi服务器性能,基于gin web框架搭建RESTful API服务

该博客介绍了使用Go语言 Gin 框架和 database/sql 包来构建Web应用并操作MySQL数据库的步骤。项目结构清晰,包括main.go、router、apis、databases和models文件夹,实现了CRUD操作。数据库连接通过sql.Open()初始化,并使用 gin.Default() 创建路由。apis中的函数处理HTTP请求,models中的Person结构体定义了数据模型并实现了数据库交互方法。博客还提及了下一步将学习GORM框架和Docker部署。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这篇主要学习go项目中的项目结构、项目规范等知识,ROM采用的database/sql的写法。

1.技术框架

利用的是ginweb框架,然后ROM层选用database/sql,安装mysql驱动。安装方式如下:

//使用github上的gin托管地址

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

$ go get github.com/go-sql-driver/mysql

2.项目结构如下

项目结构分析:

1、main.go主要是存放路由,启动项目;

2、router主要存放路由信息,然后返回一个router;

3、apis存放router的Handler函数;

4、databases存放数据连接信息;

5、models存放数据模型,类似Java中POJO对象。

│ main.go

├─.idea

│ │ go.iml

│ │ misc.xml

│ │ modules.xml

│ │ workspace.xml

│ │

│ └─inspectionProfiles

├─apis

│ person.go

├─databases

│ mysql.go

├─models

│ person.go

└─router

router.go

4e4b434d2bf9?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

3.main.go代码解释

package main

import (

//这里讲db作为go/databases的一个别名,表示数据库连接池

db "go/databases"

. "go/router"

)

func main() {

//当整个程序完成之后关闭数据库连接

defer db.SqlDB.Close()

router := InitRouter()

router.Run(":8080")

}

4.router.go代码解释

package router

import (

"github.com/gin-gonic/gin"

."go/apis"

)

func InitRouter() *gin.Engine {

router := gin.Default()

//IndexApi为一个Handler

router.GET("/", IndexApi)

router.POST("/person", AddPersonApi)

router.GET("/persons", GetPersonsApi)

router.GET("/person/:id", GetPersonApi)

router.PUT("/person/:id", ModPersonApi)

router.DELETE("/person/:id", DelPersonApi)

return router

}

5.mysql.go代码解释

package databases

import (

"database/sql"

_ "github.com/go-sql-driver/mysql"

"log"

)

//因为我们需要在其他地方使用SqlDB这个变量,所以需要大写代表public

var SqlDB *sql.DB

//初始化方法

func init() {

var err error

SqlDB, err = sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/test?parseTime=true")

if err != nil {

log.Fatal(err.Error())

}

//连接检测

err = SqlDB.Ping()

if err != nil {

log.Fatal(err.Error())

}

}

使用sql.Open()方法会创建一个数据库连接池db。这个地步不是数据库连接,它是一个连接池,只有当真正的数据库通信的时候才创建连接。例如,这里的db.Ping()操作。db.SetMaxIdleConns(20)和db.SetMaxOpenConns(20)分别设置数据库的空闲连接和最大打开连接,即向Mysql服务端发出的所有连接的最大数目。

6.models中person.go代码解释

package models

import (

"log"

db "go/databases"

)

//定义person类型结构

type Person struct {

Id int `json:"id"`

FirstName string `json:"first_name"`

LastName string `json:"last_name"`

}

func (p *Person) AddPerson() (id int64, err error) {

rs, err := db.SqlDB.Exec("INSERT INTO person(first_name, last_name) VALUES (?, ?)", p.FirstName, p.LastName)

if err != nil {

return

}

id, err = rs.LastInsertId()

return

}

func (p *Person) GetPersons() (persons []Person, err error) {

persons = make([]Person, 0)

rows, err := db.SqlDB.Query("SELECT id, first_name, last_name FROM person")

defer rows.Close()

if err != nil {

return

}

for rows.Next() {

var person Person

rows.Scan(&person.Id, &person.FirstName, &person.LastName)

persons = append(persons, person)

}

if err = rows.Err(); err != nil {

return

}

return

}

func (p *Person) GetPerson() (person Person, err error) {

err = db.SqlDB.QueryRow("SELECT id, first_name, last_name FROM person WHERE id=?", p.Id).Scan(

&person.Id, &person.FirstName, &person.LastName,

)

return

}

func (p *Person) ModPerson() (ra int64, err error) {

stmt, err := db.SqlDB.Prepare("UPDATE person SET first_name=?, last_name=? WHERE id=?")

defer stmt.Close()

if err != nil {

return

}

rs, err := stmt.Exec(p.FirstName, p.LastName, p.Id)

if err != nil {

return

}

ra, err = rs.RowsAffected()

return

}

func (p *Person) DelPerson() (ra int64, err error) {

rs, err := db.SqlDB.Exec("DELETE FROM person WHERE id=?", p.Id)

if err != nil {

log.Fatalln(err)

}

ra, err = rs.RowsAffected()

return

}

执行非query操作,使用db的Exec方法,在MySQL中使用?做占位符。最后我们把插入后的Id返回给客户端。

GetPersons方法解释:

读取MySQL的数据需要有一个绑定的过程,db.Query()方法返回一个rows对象,这个数据库连接随即转移到这个对象,因此我们需要定义rows.Close()操作,然后创建一个[]Person的切片。

使用make,而不是直接使用var persons []Person的声明方式。还是有所差别的,使用make的方式,当数组切片没有元素的时候,Json会返回[]。如果直接声明,json会返回null。

接下来就是使用rows对象的Next()方法,遍历所查询的数据,一个个绑定到person对象上,最后append到person切片。

7.apis中的person.go代码解释

package apis

import (

"net/http"

"log"

"fmt"

"strconv"

"github.com/gin-gonic/gin"

."go/models"

)

func IndexApi(c *gin.Context) {

c.String(http.StatusOK, "It works")

}

func AddPersonApi(c *gin.Context) {

firstName := c.Request.FormValue("first_name")

lastName := c.Request.FormValue("last_name")

p := Person{FirstName: firstName, LastName: lastName}

ra, err := p.AddPerson()

if err != nil {

log.Fatalln(err)

}

msg := fmt.Sprintf("insert successful %d", ra)

c.JSON(http.StatusOK, gin.H{

"msg": msg,

})

}

func GetPersonsApi(c *gin.Context) {

var p Person

persons, err := p.GetPersons()

if err != nil {

log.Fatalln(err)

}

c.JSON(http.StatusOK, gin.H{

"persons": persons,

})

}

func GetPersonApi(c *gin.Context) {

cid := c.Param("id")

id, err := strconv.Atoi(cid)

if err != nil {

log.Fatalln(err)

}

p := Person{Id: id}

person, err := p.GetPerson()

if err != nil {

log.Fatalln(err)

}

c.JSON(http.StatusOK, gin.H{

"person": person,

})

}

func ModPersonApi(c *gin.Context) {

cid := c.Param("id")

id, err := strconv.Atoi(cid)

if err != nil {

log.Fatalln(err)

}

p := Person{Id: id}

err = c.Bind(&p)

if err != nil {

log.Fatalln(err)

}

ra, err := p.ModPerson()

if err != nil {

log.Fatalln(err)

}

msg := fmt.Sprintf("Update person %d successful %d", p.Id, ra)

c.JSON(http.StatusOK, gin.H{

"msg": msg,

})

}

func DelPersonApi(c *gin.Context) {

cid := c.Param("id")

id, err := strconv.Atoi(cid)

if err != nil {

log.Fatalln(err)

}

p := Person{Id: id}

ra, err := p.DelPerson()

if err != nil {

log.Fatalln(err)

}

msg := fmt.Sprintf("Delete person %d successful %d", id, ra)

c.JSON(http.StatusOK, gin.H{

"msg": msg,

})

}

其实,整个项目的结构和CRUD操作跟Java中的思想比较类似,应该很容易上手。需要注意一点的是,如果需要将整个项目运行起来,项目的路径一定Gopath路径:F:\Go\Project\src;

4e4b434d2bf9?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

4e4b434d2bf9?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

项目启动结果如下:

4e4b434d2bf9?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

熟悉了database/sql的写法后,下一步就是学习ROM框架gorm的写法,进而学习Docker进行部署。

参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值