9月
11
返回数据这块已经处理了。现在对跨域进行处理。
# 默认跨域
r.Response.CORSDefault()
允许所有跨域是不安全的。所以得对允许的域名进行跨域,或干脆不跨域。跨域中间件完善。
func (s *sMiddleware) CORS(r *ghttp.Request) {
corsOptions := r.Response.DefaultCORSOptions()
corsOptions.AllowDomain = []string{"localhost:5173"}
corsOptions.AllowOrigin = "http://localhost:5173"
corsOptions.AllowCredentials = "false"
corsOptions.AllowMethods = "POST,GET,OPTIONS,PUT,PATCH,DELETE"
corsOptions.AllowHeaders = "Accept,Content-Type,Referer,User-Agent,Origin,X-Requested-With,X-XSRF-TOKEN,X-CSRF-TOKEN,Authorization,Time"
r.Response.CORS(corsOptions)
r.Middleware.Next()
}
这样就够了,主要设置的是允许跨的域,允许跨的请求方式,允许 header 中携带的值以及是否使用 Credentials。主要就这几个的定义。
9月
11
orm with 处理也轻微使用了下。现在来处理输出。处理大输出。抱怨总是包裹一层太久了,抱怨无论啥都返回 http 200 。现在要改变这个状况。
在处理这个问题之前,我们得先找到整个框架的返回是怎么实现的。其实,在之前也想到了用后置中间件来处理。看官方自己也确实是用后置中间件来统一处理返回的。我们建立一个自己的中间件,替换掉官方自己的中间件不就好了。
官方默认中间件。
import "github.com/gogf/gf/v2/net/ghttp"
ghttp.MiddlewareHandlerResponse
之前也说过一次。gf 中间件的函数都有且仅有一个参数 r *ghttp.Request。只要实现了该方法即可。当然 r.Middleware.Next()
这个方法是要调用的。
在这个方法之前处理的逻辑,叫前置。在这个方法之后处理的逻辑,叫后置。
go 的中间件的思路和 laravel 的也是一样的。估计其他语言也是这个思路。就是前端的 axios 等的拦截器也是有着这方面的思路。
9月
10
该后台使用 vite + ts + pnpm + vue3 + element-plus + tailwindcss 等技术栈构成。没有添加任意可视化图标等插件。以最小功能,最基础功能展现。用户可以额外添加可使用的插件逻辑。
该后台后端使用 php8.2 + laravel 10 + mysql
该后台后端 go 语言版本开发中。将使用 gframe2.5.2
源码: https://github.com/vini123/simpleAdmin
在线体验: https://www.zeipan.com/admin
权限以及密码一键复位: https://v3test.yuepaibao.com/admin/api/reset
测试账号以及密码: zhoulin@xiangrong.pro、 111111 (如果发现登录不了,可一键复位谢谢)
9月
09
goframe 没有其他 orm 的 hasOne,hasMany, belongsTo 等等这样的模型关联。 goframe 说这个对开发者有一定的心智负担。goframe 有 scanList 和 自己的 with。先了解试试用吧。
https://goframe.org/pages/viewpage.action?pageId=1114326
https://goframe.org/pages/viewpage.action?pageId=7297190
之前完成了用户的登录、注册以及个人信息的获取。这个个人信息的获取,只是单表的信息。现在想要用户的其他信息。这个时候,就需要更多的查询。
如果使用 orm,就可以通过 with 就可以搞定的。但是 with 只有定义好了规则才有用。所以,这个时候就需要组合想要的 dao 了。而 dao 是通过 gf gen dao
生的,只要表不变, dao 就不变。重复生也不变,所以就不能去修改 dao。那么只能新文件中来组合了。
因为之前定义 req 和 res 的时候,已经在 model 里边加了一个文件。那么在其中再加一个组合关系就好。
于是,修改 internal/model/admin/user.go,增加以下组合。
type User struct {
entity.Users
UserExtends *entity.UserExtends `orm:"with:user_id=id" json:"user_extends"`
Roles []map[string]interface{} `json:"roles,omitempty"`
Permissions []Permission `json:"permissions,omitempty"`
}
// 用户权限
type Permission struct {
entity.Permissions
Permission []Permission `json:"permission,omitempty"`
}
从组合中可以看到使用 orm 来获取的仅仅是扩展信息。另外的 roles 和 permissions 是另外赋值进去的。
roles 和 permissions 之所以是另外赋值。是因为它们的获取会关联更多的表。不太适合嵌套去处理。
虽然 User 中定义了 with 相关的 UserExtends。 如果调用的时候,没使用 with 也是不会去查询的。其他的两个,如果不赋值也是不会有的。最基础的 Users 依然还是 entity 里的那个 user。
后来还是改了,表名还是用复数吧。所以命令回来生成的 dao 和 model 也是复数。复数就复数吧。
9月
09
获取图片验证码、登录、获取个人信息都好了。现在做注册功能。
在 ctrl 中调整好姿势。
internal/controller/user/user_admin_sign_up.go
package user
import (
"context"
"goSimpleAdmin/api/user/admin"
model "goSimpleAdmin/internal/model/admin"
"goSimpleAdmin/internal/service"
)
func (c *ControllerAdmin) SignUp(ctx context.Context, req *admin.SignUpReq) (res *admin.SignUpRes, err error) {
data, err := service.User().SignUp(ctx, model.SignUpReq{
Nickname: req.Nickname,
Account: req.Account,
Password: req.Password,
VerifyKey: req.VerifyKey,
VerifyCode: req.VerifyCode,
})
if err != nil {
return
}
res = new(admin.SignUpRes)
res.SignUpRes = data
return res, err
}
9月
08
上一步中,生成图片验证码接口已经好了。现在完善登录和注册的业务逻辑。这里准备使用 token 的方式来维护用户的状态,选用 jwt 。所以登录或注册成功后,只需返回用户一个 token 就可以了。过期时间暂时先不要。所以登录和注册的返回需要修改一番。
登录注册输出重新定义一下
internal/model/admin/user.go 中定义输入和输出的结构。
type SignInRes struct {
Token string `json:"token"`
}
type SignUpRes struct {
Token string `json:"token"`
}
api/user/admin/user.go 中组合输入输出
package admin
import (
model "goSimpleAdmin/internal/model/admin"
"github.com/gogf/gf/v2/frame/g"
)
type SignInRes struct {
model.SignInRes
}
type SignUpRes struct {
model.SignUpRes
}
因为 api 定义的时候已经定义好了输出。所以 ctrl 和 service 这些不需要再重新生一次了。
但是在 logic 和 service 中没有定义 res。所以需要补上,再重新生一次。 service 就是接口的定义,实现还是在 logic 中。
9月
07
随着业务逻辑的充实,发现前边有些地方还是需要修改和完善。哪里呢。就是最最开始的地方,就是定义 api 的那地方。其实在那里,最开始,只需要定义 Req 和 Res。里边不需要先填充任意的东西。为什么这么说呢。因为 路由指向 ctrl,ctrl 通过 service 的绑定去调用 logic。而 logic 里的输入输出却是在 mode 里定义的。所以,model 里边的输入输出和 api 里的输入输出一般都是一样的。这个时候,只需要定义 model 里的输出输出。 api 那边直接继承过来就可以了。所以,步骤是这样的。
- 定义 api 里的 req 和 res,空的就行(接口path 和 method 还是要加上),名字和方法名字想好。执行
gf gen ctrl
生就好。
- 然后再生成 dao 和 model。 执行
gf gen dao
生就好。
- 再在 model 下定义输入和输出。这个定义输入和输出也有一点矛盾。是业务场景带来的。model 和 dao 自身一般是不会有矛盾的,因为他们对应的数据库里的表。而输出和输入却要对应业务场景。比如一个项目有后台登录和 app 登录两个场景。往往,会分出两个路由组来处理这两种业务场景。虽然都是登录,输入和输出一般都不会都是相同的。这个时候 model 下定义输入和输出就得加个分组了。比如当前逻辑是后台逻辑。我会在 internal/model/ 下再多建立一层文件夹,就叫 admin。然后在里边再建立对应的输入输出文件。其实叫的这个 admin 和 api 下的文件夹是一个意思。就是初始化项目时候 api 下的 v1 的意思。这个时候都是 v1 或都是 admin,继承的时候就要用别名哈。下边会给出例子。
- 再去建立 logic 的初步实现。然后去生 service,再回头完善 logic。
gf gen service
在 api req 的时候,里边一定要有 g.Meta。否则,不会生成对应的 ctrl 文件。
go 语言刚开始学,goframe 也是第一次用。如果理解错了,可以留言哈。
9月
07
从 http 请求到自定义路由,再对应的返回已经跑通了。但是,还没具体的实现业务。那就先从图片验证码开始。从以下几点开始。
- 先去找一个比较成熟的生成图片验证码的库
- 写生成逻辑,并加入缓存功能。比如缓存 5 分钟。
- 添加配置。图片的默认宽高,复杂度等。以及上边说的缓存 5 分钟这些,最好有一个统一配置。
- 再就是核验验证码(该步骤留到需要使用验证码的地方使用)
redis 配置
在做这些之前,我们先把 redis 配置和使用搞好。就是准备使用 redis 来对图片验证码的值进行缓存。
goframe 官方配置介绍: https://goframe.org/pages/viewpage.action?pageId=1114194
redis 官方介绍: https://goframe.org/display/gf/NoSQL+Redis
配置文件的文件类型就使用 yaml,配置文件就放在 *manifest/config下。
好吧。那么就在 *manifest/config/config.yaml 下补充。
# Redis 配置
redis:
default:
address: 192.168.56.56:6379
db: 1
cache:
address: 192.168.56.56:6379
db: 2
配置好了,那就开始使用测试下看看。
9月
06
做项目。一般都会选择框架。很少会直接从 0 开始撸的。之所以选择框架,是因为框架既帮你做好了架构,又准备好了很多工具,还定制了一些规范。适合快速稳定的做项目。一般一个语言对应的开源框架会比较多,选一个或两个应用到项目中就可以了。准备进入 go 领域,也得选一个框架。初步了解了 gin 和 goframe。这里还是选择 goframe。gin 还是太轻了,项目中需要的一些工具不够多和完善。
官网: https://goframe.org/
安装升级
这里想做一个接口服务项目。仅仅提供接口给到前端使用就好。现在大多业务场景都是前后端分离的。比如app、小程序、管理后台这些。app,小程序是必须分离。管理后台也可以不分离,但分离起来更好写更爽。
按照官网文档,先安装好 gf。当前最新版本是 2.5.2。
创建项目。
gf init goSimpleAdmin
cd goSimpleAdmin
# 查看版本信息
gf -v
GoFrame CLI Tool v2.5.2, https://goframe.org
GoFrame Version: v2.3.1 in current go.mod
CLI Installed At: /Users/vini123/go/bin/gf
CLI Built Detail:
Go Version: go1.20.6
GF Version: v2.5.2
Git Commit: 2023-08-18 09:57:25 cf299273c499aafb5d19829809dfb6b8ef280c12
Build Time: 2023-08-18 16:23:18
发现 goframe 版本是 2.3.1。可以对刚创建的项目进行升级。在升级前,先做好版本控制。
git init -b main
git add .
git commit -m 'goframe initialize'
使用 gf up
对项目进行升级。
9月
06
既然 go 的迁移、seeder 等不好用,还是用 laravel 来搞吧。
开始
composer create-project laravel/laravel youme.com --prefer-dist
这样就创建了一个最新的 laravel 项目,项目文件在 youme.com 里。在本地,做了 host 映射。通过 youme.com 就可以打开。
上边就是默认的。
创建 git 版本控制,提交。
git init -b main
git add .
git commit -m 'laravel initialize'