GoFiber 从零系列(一):项目创建&配置文件&gorm-mysql
GoFiber 从零系列(二):热加载/热更新 && 日志系统 && 验证入参
起步
通过创建文件夹并在文件夹内运行 go mod init github.com/your/repo
,来初始化项目,然后使用 go get
命令安装 Fiber:
go get -u github.com/gofiber/fiber/v2
选用 go-ini/ini编写配置
go get -u github.com/go-ini/ini
一、Hello World
新建文件夹conf,创建app.ini
RUN_MODE = dev
[app]
PAGE_SIZE = 10
JWT_SECRET = 23347$040412
JWT_SALT = jinpika
[server]
HTTP_PORT = 9999
READ_TIMEOUT = 60
WRITE_TIMEOUT = 60
[database]
TYPE = mysql
USER = 数据库账号
PASSWORD = 数据库密码
#127.0.0.1:3306
HOST = 127.0.0.1:3306
NAME = 数据库名
新建文件夹pkg,创建子文件夹setting,创建setting.go
package setting
import (
"log"
"time"
"github.com/go-ini/ini"
)
var (
Cfg *ini.File
RunMode string
HTTPPort int
ReadTimeout time.Duration
WriteTimeout time.Duration
PageSize int
JwtSecret string
)
func init() {
var err error
Cfg, err = ini.Load("conf/app.ini")
if err != nil {
log.Fatal("Fail to parse 'conf/app.ini': %v", err)
}
LoadBase()
LoadServer()
LoadApp()
}
func LoadBase() {
RunMode = Cfg.Section("").Key("RUN_MODE").MustString("dev")
}
func LoadServer() {
sec, err := Cfg.GetSection("server")
if err != nil {
log.Fatal("Fail to get section 'server': %v", err)
}
HTTPPort = sec.Key("HTTP_PORT").MustInt(8000)
ReadTimeout = time.Duration(sec.Key("READ_TIMEOUT").MustInt(60)) * time.Second
WriteTimeout = time.Duration(sec.Key("WRITE_TIMEOUT").MustInt(60)) * time.Second
}
func LoadApp() {
sec, err := Cfg.GetSection("app")
if err != nil {
log.Fatal("Fail to get section 'app': %v", err)
}
JwtSecret = sec.Key("JWT_SECRET").MustString("!@)*#)!@U#@*!@!)")
PageSize = sec.Key("PAGE_SIZE").MustInt(10)
}
在根目录创建main.go
package main
import (
"fmt"
"github.com/gofiber/fiber/v2"
"github.com/jinpikaFE/go_fiber/pkg/setting"
)
func main() {
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
app.Listen(fmt.Sprintf(":%d", setting.HTTPPort))
}
当前目录结构
go-fiber/
├── conf
│ - app.ini
├── pkg
│ └── setting
│ └── setting.go
│ - main.go
启动项目
go run main.go
打开 http://127.0.0.1:9999 可以看到 Hello, World!
二、路由配置
新建routers文件夹,创建router.go
package routers
import (
"github.com/gofiber/fiber/v2"
controller "github.com/jinpikaFE/go_fiber/controllers"
)
func InitRouter() *fiber.App {
app := fiber.New()
apiv1 := app.Group("/v1")
{
apiv1.Get("/test", controller.GetTests)
}
return app
}
创建controllers文件夹,创建test.go
package controller
import "github.com/gofiber/fiber/v2"
// 获取Test列表
func GetTests(c *fiber.Ctx) error {
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"message": "test",
})
}
修改main.go
package main
import (
"fmt"
"github.com/jinpikaFE/go_fiber/pkg/setting"
"github.com/jinpikaFE/go_fiber/routers"
)
func main() {
app := routers.InitRouter()
app.Listen(fmt.Sprintf(":%d", setting.HTTPPort))
}
重启项目
使用postman 或者 打开 http://localhost:9999/v1/test
可以看到如下数据结构
{
"message": "test"
}
当前目录结构
go-fiber/
├── conf
│ - app.ini
├── controllers
│ - test.go
├── pkg
│ └── setting
│ └── setting.go
├── routers
│ - router.go
│ - main.go
三、使用gorm操作mysql数据库
拉取gorm
的依赖包
go get -u github.com/jinzhu/gorm
拉取mysql
驱动的依赖包
go get -u github.com/go-sql-driver/mysql
创建test表
CREATE TABLE `test` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT '' COMMENT '名称',
`created_on` int(10) unsigned DEFAULT '0' COMMENT '创建时间',
`modified_on` int(10) unsigned DEFAULT '0' COMMENT '修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
新建models文件夹 新建model.go
package models
import (
"fmt"
"log"
"github.com/jinpikaFE/go_fiber/pkg/setting"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
var db *gorm.DB
// 所有表都统一加入下面三个字段
type Model struct {
ID int `gorm:"primary_key" json:"id"`
CreatedOn int `json:"created_on"`
ModifiedOn int `json:"modified_on"`
}
func init() {
var (
err error
dbType, dbName, user, password, host string
)
sec, err := setting.Cfg.GetSection("database")
if err != nil {
log.Fatal(2, "Fail to get section 'database': %v", err)
}
dbType = sec.Key("TYPE").String()
dbName = sec.Key("NAME").String()
user = sec.Key("USER").String()
password = sec.Key("PASSWORD").String()
host = sec.Key("HOST").String()
db, err = gorm.Open(dbType, fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True&loc=Local",
user,
password,
host,
dbName))
if err != nil {
log.Fatal(err)
}
db.SingularTable(true)
db.LogMode(true)
db.DB().SetMaxIdleConns(10)
db.DB().SetMaxOpenConns(100)
}
func CloseDB() {
defer db.Close()
}
新建test.go
package models
import (
"time"
"github.com/jinzhu/gorm"
)
type Test struct {
Model
// query tag是query参数别名,json xml,form适合post
Name string `query:"name" json:"name" xml:"name" form:"name"`
}
func GetTests(pageNum int, pageSize int, maps interface{}) (tests []Test) {
db.Where(maps).Offset(pageNum).Limit(pageSize).Find(&tests)
return
}
func AddTest(test *Test) bool {
db.Create(&test)
return true
}
func EditTest(id int, data interface{}) bool {
db.Model(&Test{}).Where("id = ?", id).Updates(data)
return true
}
func DeleteTest(id int) bool {
db.Where("id = ?", id).Delete(Test{})
return true
}
// 根据id判断test 对象是否存在
func ExistTestByID(id int) bool {
var test Test
db.Select("id").Where("id = ?", id).First(&test)
return test.ID > 0
}
// gorm所支持的回调方法:
// 创建:BeforeSave、BeforeCreate、AfterCreate、AfterSave
// 更新:BeforeSave、BeforeUpdate、AfterUpdate、AfterSave
// 删除:BeforeDelete、AfterDelete
// 查询:AfterFind
func (test *Test) BeforeCreate(scope *gorm.Scope) error {
scope.SetColumn("CreatedOn", time.Now().Unix())
return nil
}
func (test *Test) BeforeUpdate(scope *gorm.Scope) error {
scope.SetColumn("ModifiedOn", time.Now().Unix())
return nil
}
修改controllers 下的test.go
package controller
import (
"log"
"strconv"
"github.com/gofiber/fiber/v2"
"github.com/jinpikaFE/go_fiber/models"
)
// var (
// me
// )
// 获取Test列表
func GetTests(c *fiber.Ctx) error {
// maps := make(map[string]interface{})
// // 获取get query参数 或者使用queryparser
// id := c.Query("id")
// maps["id"] = id
maps := &models.Test{}
c.QueryParser(maps)
res := models.GetTests(0, 10, maps)
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"code": 200,
"message": "SUCCESS",
"data": res,
"query": maps,
})
}
// 添加test
func AddTest(c *fiber.Ctx) error {
test := &models.Test{}
c.BodyParser(test)
res := models.AddTest(test)
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"code": 200,
"message": "SUCCESS",
"data": res,
})
}
// 编辑test
func EditTest(c *fiber.Ctx) error {
id, err := strconv.Atoi(c.Params("id"))
test := &models.Test{}
c.BodyParser(test)
code := 200
res := false
message := "SUCCESS"
if err != nil {
log.Fatal(err)
}
if models.ExistTestByID(id) {
res = models.EditTest(id, test)
} else {
code = 500
}
if res {
message = "SUCCESS"
} else {
message = "ERROR"
}
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"code": code,
"message": message,
"data": res,
})
}
// 删除test
func DelTest(c *fiber.Ctx) error {
id, err := strconv.Atoi(c.Params("id"))
code := 200
res := false
message := "SUCCESS"
if err != nil {
log.Fatal(err)
}
if models.ExistTestByID(id) {
res = models.DeleteTest(id)
} else {
code = 500
}
if res {
message = "SUCCESS"
} else {
message = "ERROR"
}
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"code": code,
"message": message,
"data": res,
})
}
修改routers 的router.go
package routers
import (
"github.com/gofiber/fiber/v2"
controller "github.com/jinpikaFE/go_fiber/controllers"
)
func InitRouter() *fiber.App {
app := fiber.New()
apiv1 := app.Group("/v1")
{
apiv1.Get("/test", controller.GetTests)
apiv1.Post("/test", controller.AddTest)
apiv1.Put("/test/:id", controller.EditTest)
apiv1.Delete("/test/:id", controller.DelTest)
}
return app
}
当前目录结构
go-fiber/
├── conf
│ - app.ini
├── controllers
│ - test.go
├── models
│ - model.go
│ - test.go
├── pkg
│ └── setting
│ └── setting.go
├── routers
│ - router.go
│ - main.go
go run main.go 重启应用