1.1引言
在当前的互联网时代,Web应用程序已成为企业和服务提供者与用户互动的重要渠道。随着业务需求的日益复杂,我们需要一个结构清晰、易于维护和扩展的Web框架来支撑我们的应用。本项目旨在使用Go语言及其Web框架Gin构建一个高性能、模块化的Web服务。
1.2 分层结构
- 视图层(Controller) :负责接收前端请求,调用逻辑层处理请求,并返回响应。
- 逻辑层(Service) :负责处理具体的业务逻辑,如参数校验、数据处理等。
- 数据层(Repository) :负责与数据库交互,执行增删改查等操作。
1.3 组件工具
Gin高性能go web框架:github.com/gin-gonic/g…
Go Mod
- go mod init
- go get gopkg.in/gin-gonic/gin.v1@v1.3.0
1.4 Respository(数据层)
数据库操作
- 安装myswl数据库依赖:go get -u github.com/go-sql-driver/mysql
- 数据库链接操作
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql" //导入包但不使用,init()
)
// Go连接Mysql示例
func main() {
//数据库
//用户名:密码啊@tcp(ip:端口)/数据库的名字
dsn := "root:123456@tcp(127.0.0.1:3306)/test"
//连接数据集
db, err := sql.Open("mysql", dsn) //open不会检验用户名和密码
if err != nil {
fmt.Printf("dsn:%s invalid,err:%v\n", dsn, err)
return
}
err = db.Ping() //尝试连接数据库
if err != nil {
fmt.Printf("open %s faild,err:%v\n", dsn, err)
return
}
fmt.Println("连接数据库成功~")
//设置数据库连接池的最大连接数
db.SetMaxIdleConns(10)
return
}
- 数据库的插入操作
func insert() {
sqlStr := `INSERT into user(name,age) values("乐",22)` //sql语句
ret, err := db.Exec(sqlStr) //执行sql语句
if err != nil {
fmt.Printf("插入失败,err:%v\n", err)
return
}
//如果是插入数据的操作,能够拿到插入数据的id
id, err := ret.LastInsertId()
if err != nil {
fmt.Printf("err:%v\n", err)
return
}
fmt.Println("id", id)
}
- 数据库删除操作
func deleteRow(id int) {
sqlStr := `Delete from user where id=?`
ret, err := db.Exec(sqlStr, id)
if err != nil {
fmt.Printf("删除失败,err:%v\n", err)
return
}
n, _ := ret.RowsAffected()
fmt.Printf("删除了%d行数据\n", n)
}
- 数据库更新操作
func updateRow(newAge int, id int) {
sqlStr := `Update user set age=? where id=?`
ret, err := db.Exec(sqlStr, newAge, id)
if err != nil {
fmt.Printf("update failed ,err:%v\n", err)
return
}
n, _ := ret.RowsAffected()
fmt.Printf("更新了%d行数据\n", n)
}
-数据库查询操作
type user struct {
id int
name string
age int
}
func query(id int) *user {
//1.查询单挑记录的sql语句 ?是参数
sqlStr := "select id,name,age from user where id=?;"
//2.执行
rowObj := db.QueryRow(sqlStr, id) // 查询得到整条记录
//3.拿到结果
var u1 user
rowObj.Scan(&u1.id, &u1.name, &u1.age)
//打印结果
fmt.Printf("u1:%#v\n", u1)
return &u1
}
1.5 Service(逻辑层)
Service层流程:参数校验->准备数据->组装实体
// Do 方法执行查询页面信息的流程
func (f *QueryPageInfoFlow) Do() (*PageInfo, error) {
if err := f.checkParam(); err != nil {
return nil, err
}
if err := f.prepareInfo(); err != nil {
return nil, err
}
if err := f.packPageInfo(); err != nil {
return nil, err
}
return f.pageInfo, nil
}
1.5.1 参数校验
- 参数校验就是验证参数的合法性,在项目里要做严格的参数校验
// checkParam 检查参数是否合法
func (f *QueryPageInfoFlow) checkParam() error {
if f.topicId <= 0 {
return errors.New("topic id must be larger than 0")
}
return nil
}
1.5.2 参数校验
- 在数据准备部分,调用数据层定义的查询方法,得到数据
1.5.3 组装实体
- 在组装实体部分,将数据层返回的数据转换为业务实体
1.6 Controller(视图层)
- 在视图层主要为了构建View对象,返回给前端需要的数据
type PageData struct {
Code int64 `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
func QueryPageInfo(topicIdStr string) *PageData {
//参数转换
topicId, err := strconv.ParseInt(topicIdStr, 10, 64)
if err != nil {
return &PageData{
Code: -1,
Msg: err.Error(),
}
}
//获取service层结果
pageInfo, err := service.QueryPageInfo(topicId)
if err != nil {
return &PageData{
Code: -1,
Msg: err.Error(),
}
}
return &PageData{
Code: 0,
Msg: "success",
Data: pageInfo,
}
}
1.7 Router
- 监听前端的请求,并返回给前端数据
func main() {
// 初始化应用程序,如果初始化失败则退出程序
if err := Init(); err != nil {
os.Exit(-1)
}
// 创建一个默认的 Gin 路由器
r := gin.Default()
// 使用 Gin 的 Logger 中间件记录请求日志
r.Use(gin.Logger())
// 定义一个处理 GET 请求的路由
r.GET("/community/page/get/:id", func(c *gin.Context) {
// 从 URL 参数中获取 topicId
topicId := c.Param("id")
// 调用 handler 包中的 QueryPageInfo 函数获取数据
data := handler.QueryPageInfo(topicId)
// 返回 JSON 格式的数据给客户端
c.JSON(200, data)
})
// 启动服务器,监听指定的端口
err := r.Run()
// 如果启动服务器时发生错误,则返回
if err != nil {
return
}
}
func Init() error {
if err := repository.Init(); err != nil {
return err
}
if err := util.InitLogger(); err != nil {
return err
}
return nil
}