go系列 go-admin-core

2023-10-06 18:43:21 浏览数 (2)

这一章节主要学习通过go-admin-core 快速开发一个简单的web项目并做好三层模型分层。

gin

gin 是一个web框架,我们通过 go mod 来使用gin框架进行http接口的开发:

代码语言:javascript复制
go mod init go-test
go get -u github.com/gin-gonic/gin

我们写一个main方法启动一个http接口。在go 中main 方法必须在main包之下,不同于java中的包必须是物理包,go中的包可以是逻辑包:

代码语言:javascript复制
package main

import "github.com/gin-gonic/gin"

func main() {
 r := gin.Default()
 r.GET("/", func(c *gin.Context) {
  c.JSON(200, gin.H{
   "message": "TEST",
  })
 })
 r.Run() // listen and serve on 0.0.0.0:8080
}

运行 go mod tidy 更新依赖,启动main方法,访问8080接口:

gorm

接下来我们学习gorm的基本使用,安装gorm 和驱动包:

代码语言:javascript复制
go get -u github.com/jinzhu/gorm
go get -u gorm.io/driver/mysql

测试连接数据库:

代码语言:javascript复制
username := "root"              // 账号
password := "123456" // 密码
host := "127.0.0.1"             // 地址
port := 3306                    // 端口
DBname := "test"               // 数据库名称
timeout := "10s"                // 连接超时,10秒
str := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local&timeout=%s", username, password, host, port, DBname, timeout)
db, err := gorm.Open(mysql.Open(str), &gorm.Config{})
if err != nil {
    panic("failed to connect mysql.")
}

至于gorm的查询api用法在后续的web开发中介绍。

go-admin-core

基本了解了上面两大框架,我们直接进入实战,前文说说过,关于go的一些语法细节我们边开发边学习,不必太担心。go-admin-core 是集成并封装了 log,gorm,gin,简化了我们的开发难度,感兴趣的同学可以去阅读一下源码。这里我展示一下这个框架的怎么去使用。main.go源码:

代码语言:javascript复制
package main

import (
 "poseidon-go/app/admin/router"
)

func main() {
 router.InitRouter()
}


router.go源码:

代码语言:javascript复制
package router

import (
 "github.com/gin-gonic/gin"
 _ "github.com/gin-gonic/gin"
 log "github.com/go-admin-team/go-admin-core/logger"
 "github.com/go-admin-team/go-admin-core/sdk"
 "gorm.io/driver/mysql"
 "gorm.io/gorm"
 "os"
 "poseidon-go/app/admin/config"
)

var RouterList = make([]func(*gin.RouterGroup), 0)

// InitRouter 路由初始化,不要怀疑,这里用到了
func InitRouter() {
 var r *gin.Engine
 h := sdk.Runtime.GetEngine()
 if h == nil {
  h = gin.New()
  sdk.Runtime.SetEngine(h)
 }
 switch h.(type) {
 case *gin.Engine:
  r = h.(*gin.Engine)
 default:
  log.Fatal("not support other engine")
  os.Exit(-1)
 }
 db, err := gorm.Open(mysql.Open("root:root@tcp/vcp_saas?charset=utf8&parseTime=True&loc=Local"), &gorm.Config{})
 if err != nil {
  log.Error(err)
 }
 sdk.Runtime.SetDb("*", db)
 // 这个必须在路由组之前设置,否则无效
 config.InitMiddleware(r)
 // 可根据业务需求来设置接口版本
 v1 := r.Group("/api/v1")
 for _, f := range RouterList {
  f(v1)
 }
 r.Run(":8080")
}

在这里有几个知识点

  1. p,p,&p 的区别:不同于java ,go 中内存和内存指针是分开的。p 代表当前的内存,p代表当前内存的指针,&p代表当前内存的地址也就是指针的值。

举例:

代码语言:javascript复制
func main() {
 var p *int
 p = new(int)
 *p = 1
 fmt.Println(p, &p, *p)
}
 
输出
0xc04204a080  0xc042068018  1

扩展一下,如果我再设置一个 *p=2,它的内存地址是变还不变?我们知道,go也是有垃圾回收器的,对比java,我们给一个对象变量赋新值,它是新开辟内存还是覆盖原来的内存,小伙伴们可以思考一下go和java在这个语法上的差别。

  1. 类型, .()被称为类型断言,可以将一个interface{}类型的变量转换成其它类型 ,type 关键字是类型关键字,用于定义类型和结构体。示例:
代码语言:javascript复制
 var i interface{}
 i="sss"
 fmt.Println(i.(string))
 router.InitRouter()
  1. go 中的包,包是通过import导入的,可以给包起别名,可以直接通过包名调用包中的大写字母开头的所有方法,示例:
代码语言:javascript复制
package main

import (
 v1 "poseidon-go/app/admin/router"
)

func main() {
 v1.InitRouter()
 v1.Test()
}


InitRouter 方法和Test方法并不在同一个go文件中,但是同包。语法介绍完了,我们写一个三层分层的接口:先注册路由器

代码语言:javascript复制
package router

import (
 "github.com/gin-gonic/gin"
 "poseidon-go/app/admin/apis"
)

func init() {
 RouterList = append(RouterList, registerTestRouter)
}

func registerTestRouter(v1 *gin.RouterGroup) {
 api := apis.Test{}
 r := v1.Group("/test")
 {
  r.GET("/a", api.GetPage)

 }
}

然后写一个controller,实现数据绑定和调service

代码语言:javascript复制
package apis

import (
 "github.com/gin-gonic/gin"
 "github.com/gin-gonic/gin/binding"
 "github.com/go-admin-team/go-admin-core/sdk/api"
 "poseidon-go/app/admin/model/dto"
 "poseidon-go/app/admin/service"
)

type Test struct {
 api.Api
}

// 函数名称前面的括号是Go定义这些函数将在其上运行的对象的方式
func (e Test) GetPage(c *gin.Context) {
 req := dto.TestReq{}
 // 结构体初始化
 s := service.Test{}
 // IOC 手动挡
 err := e.MakeContext(c).
  MakeOrm().
  Bind(&req, binding.Form).
  MakeService(&s.Service).
  Errors
 if err != nil {
  e.Logger.Error(err)
  e.Error(500, err, err.Error())
  return
 }
 err = s.Message(&req).Error
 e.OK(">>>>", "xxxxxxxxxxxxx")
}

再实现service:

代码语言:javascript复制
package service

import (
 "errors"
 "github.com/go-admin-team/go-admin-core/sdk"
 "gorm.io/gorm"
 "poseidon-go/app/admin/model/dto"

 "github.com/go-admin-team/go-admin-core/sdk/service"
)

type Test struct {
 service.Service
}

// GetPage 获取SysApi列表
func (e *Test) Message(req *dto.TestReq) *Test {
 db := sdk.Runtime.GetDbByKey("*")
 var str, model string
 err := db.Model(&str).Scopes().
  First(model, req.GetType()).Error
 if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
  err = errors.New("查看对象不存在或无权查看")
  e.Log.Errorf("Service GetSysApi error:%s", err)
  _ = e.AddError(err)
  return e
 }
 if err != nil {
  e.Log.Errorf("db error:%s", err)
  _ = e.AddError(err)
  return e
 }
 return e
}

这里的知识点主要是方法和结构体的绑定 func (e *Test) Message。方法前面的括号就是将该方法和结构体绑定在一起。

小结

上面代码介绍了基于go-admin-core 实现的三层分层的web代码,下一章节我们接着讲在gin中使用 gorm。

祝大家国庆快乐

0 人点赞