2022.05.06 18:46:36
配置go mod proxy
,参考https://goproxy.cn即可。
安装VSCode+Go插件或者Goland等开发工具都可以。
最近得在Linux上编译个服务端程序,所以把配置方法记录一下。
源用的是USTC的。看了他们官网发现东西还真不少比隔壁tuna多多了而且域名还短(确信)。golang直接下载太慢所以走镜像站。链接在这,时效性应该不用太担心。
https://mirrors.ustc.edu.cn/golang/go1.20.1.linux-amd64.tar.gz
步骤很简单,就是wget
然后tar
解压到指定位置最后把目录加到系统环境变量里边:
VER="1.20.1"
SH="bash"
# 下载解压 & 移除旧版本
wget https://mirrors.ustc.edu.cn/golang/go"$VER".linux-amd64.tar.gz \
&& rm -rf /usr/local/go \
&& tar -C /usr/local -zxf go$GO_STR.linux-amd64.tar.gz
# 如果是第一次安装且使用bash
echo "export PATH=$PATH:/usr/local/go/bin" >> ~/."$SH"rc
注意:执行上面的脚本之前请先自行验证安全性。以及,上面的脚本得用root权限执行。
然后就是设置代理。我用http://goproxy.cn比较多。配置也很简单:
export GO111MODULE=on
export GOPROXY=https://goproxy.cn
报错内容:call has possible formatting directive %v
原因:go test
中不能使用
fmt.Println("%v", v)
使用 fmt.Printf("%+v", v)
现代语言最大的优势就是工具链。
go tool dist list
依赖:
ldd [bin-name]
静态编译:
CGO_ENABLED=0 go build xxx
# or this
go build xxx -ldflags '-linkmode "external" -extldflags "-static"'
如果glibc版本不对的话,直接使用指定LD_LIBRARY_PATH=.
的方法是无效的。
>ref:Glibc
is hard-coded in the program
采用组合的方式将常用的范式写成函数,同时不失灵活性和潜力。
对于Gin的复用主要是添加路由的方式进行抽象和标准化,同时编写一些较为通用的API Handlers:
func APIBuilder(router gin.IRouter, handlers ...func(*gin.RouterGroup) *gin.RouterGroup) func(gin.IRouter, string) *gin.RouterGroup {
return func(router gin.IRouter, path string) *gin.RouterGroup {
group := router.Group(path)
for _, handler := range handlers {
group = handler(group)
}
return group
}
}
上面的函数实现了为一个gin.RouterGroup
自动添加参数传入的handler列表。这样的构造器构造出的函数能用于给一个接口添加几个固定的Handler。在复用层面实现了快速的为一个结构体添加CRUD的能力,同时允许你编写自己的handler代码,以及自己的构造器。
func AddCRUD[T any](router gin.IRouter, path string, db *gorm.DB) *gin.RouterGroup {
return APIBuilder(router, func(group *gin.RouterGroup) *gin.RouterGroup {
group.GET("", getAll[T](db))
group.GET("/:id", get[T](db))
group.POST("", create[T](db))
group.PUT("/:id", update[T](db))
group.DELETE("/:id", delete[T](db))
return group
})(router, path)
}
上面展示的就是构造器的一个用法,这个构造器构造的函数能用来快速给一个结构体添加CRUD接口。
其中的Handler可以自己实现,并把自己的Handler通过上面的APIBuilder打包成一个可以快速调用的函数:
// 简单的Handler示范
func create[T any](db *gorm.DB) func(c *gin.Context) {
return func(c *gin.Context) {
var d T
if err := c.ShouldBindJSON(&d); err != nil {
c.AbortWithStatus(404)
log.Println("[gorm]parse creation data failed: ", err)
} else {
if err := db.Create(&d).Error; err != nil {
c.AbortWithStatus(404)
log.Println("[gorm]create data failed: ", err)
} else {
c.JSON(200, d)
}
}
}
}
// 简单的调用示范
type Hello struct {
Hello string
World string
}
r := gin.Default
db, _ := gorm.Open(sqlite.Open("test"), &gorm.Config{})
AddCRUD[Hello](r, "/hello", db)
上面几行代码就添加了四个对于Hello的CRUD API。
而且你应该注意到了,上面crud的实现我传入了gorm.DB
来完成实际的crud动作。主要是因为数据库查询的动作我不知道应该怎么传入,而且又不想自己搓个大而全的框架出来——简洁的函数更合我的胃口。
下一步就是尝试抽象以前自己编写的后端,试着用简洁又不失灵活度的方法创建一个渐进式辅助函数包。
最近发现了go-zero这个脚手架,主打面向
k8s
整微服务开发。框架做的还行,甚至基于go语法搓了个DSL出来。里边包含的单体微服务的框架对我有比较大的启发作用,我打算把它变成一个更FP的工具包拿来用。 以及Goland好像看着确实不错。