Go-Spring 轻装上阵,重新出发 v1.0.0 !

2023-11-03 10:25:13 +08:00
 limpo

前言

多年前曾经梦想着能有一天能在 Go 语言中使用上 Spring 那样强大的框架,幸运的是我找到了go-spring,一款类似 Spring 的库,我很喜欢它,并且在我的项目中深度使用它,它给我带来了非常酷的编程体验。

然而很不幸的是最近 go-spring 停止更新了(最近的一次提交停留在九个月之前),一些问题无法得到有效的解决,因此我决定创建一个基于 go-spring 的开源库,我为它修复了一系列 bug ,并添加了一些新得特性,并对代码结构进行了简化,将外部生态从核心库中移除,仅保留核心功能,外部生态预计将来将作为独立的仓库存在,我将持续继续将它维护下去,也希望有感兴趣的人可以一起参与进来一起持续开发它。

仓库地址: https://github.com/go-spring-projects/go-spring

特性

动态属性例子

允许在运行时动态刷新属性,不仅支持基本数据类型,还支持结构、切片和 Map 类型。

package main

import (
	"fmt"
	"log/slog"
	"net/http"

	"github.com/go-spring-projects/go-spring/dync"
	"github.com/go-spring-projects/go-spring/gs"
)

type Handler struct {
	Open dync.Bool `value:"${server.open:=true}"`
}

func (h *Handler) OnInit(ctx gs.Context) error {

	http.HandleFunc("/server/status", func(writer http.ResponseWriter, request *http.Request) {
		if !h.Open.Value() {
			http.Error(writer, "server closed", http.StatusNotAcceptable)
			return
		}

		fmt.Fprint(writer, "server running")
	})
	return nil
}

type Server struct {
	Logger *slog.Logger `logger:""`
}

func (s *Server) OnInit(ctx gs.Context) error {

	props := ctx.(gs.Container).Properties()

	http.HandleFunc("/server/status/open", func(writer http.ResponseWriter, request *http.Request) {
		props.Set("server.open", "true")
		s.Logger.Info("server opened")
	})

	http.HandleFunc("/server/status/close", func(writer http.ResponseWriter, request *http.Request) {
		props.Set("server.open", "false")
		s.Logger.Info("server closed")
	})

	go func() {
		http.ListenAndServe(":7878", nil)
	}()

	return nil
}

func main() {

	gs.Object(new(Handler))
	gs.Object(new(Server))

	if err := gs.Run(); nil != err {
		panic(err)
	}
}


// Output:
// 
// $ curl http://127.0.0.1:7878/server/status
// server running
//
// $ curl http://127.0.0.1:7878/server/status/close
//
// $ curl http://127.0.0.1:7878/server/status
// server closed
//
// $ curl http://127.0.0.1:7878/server/status/open
//
// $ curl http://127.0.0.1:7878/server/status
// server running

参数校验器例子

Go-Spring允许您注册自定义值验证器。如果值验证失败,则Go-Spring将在启动阶段报告一个错误。

在这例子中, 我们将使用 go-validator/validator, 您可以参考这个示例来注册您的自定义验证器。

package main

import (
	"fmt"
	"log/slog"

	"github.com/go-spring-projects/go-spring/conf"
	"github.com/go-spring-projects/go-spring/gs"
	"gopkg.in/validator.v2"
)

const validatorTagName = "validate"

type validatorWrapper struct {
	validator *validator.Validator
}

func (v *validatorWrapper) Field(tag string, i interface{}) error {
	if 0 == len(tag) {
		return nil
	}
	return v.validator.Valid(i, tag)
}

func init() {
	conf.Register(validatorTagName, &validatorWrapper{validator: validator.NewValidator().WithTag(validatorTagName)})
}

//--------------------------------------------------------------------------

type DBOptions struct {
	UserName string `value:"${username}"`
	Password string `value:"${password}"`
	IP       string `value:"${ip}"`
	Port     int32  `value:"${port}" validate:"min=1024,max=65535"`
	DB       string `value:"${db}" validate:"nonzero"`
}

type MysqlDatabase struct {
	Logger  *slog.Logger `logger:""`
	Options DBOptions    `value:"${db}"`
}

func (md *MysqlDatabase) OnInit(ctx gs.Context) error {
	md.Logger.Info("mysql connection summary",
		"url", fmt.Sprintf("mysql://%s:%s@%s:%d/%s", md.Options.UserName, md.Options.Password, md.Options.IP, md.Options.Port, md.Options.DB))
	return nil
}

func main() {

	gs.Property("db.username", "admin")
	gs.Property("db.password", "123456")
	gs.Property("db.ip", "127.0.0.1")
	gs.Property("db.port", "0") // set db.port=0
	gs.Property("db.db", "test")

	gs.Object(new(MysqlDatabase))

	if err := gs.Run(); nil != err {
		panic(err)
	}
}

//
// Output:
// panic: container refresh failed
// ↳object bean "main/main.MysqlDatabase:MysqlDatabase" /projects/go-project/gocase/validator/main.go:58
// ↳bind MysqlDatabase.Options error: validate MysqlDatabase.Options.Port error: less than min

更多特性请参考说明: go-spring-projects/go-spring

最后还要感谢原作者lvan100的辛勤付出。

6912 次点击
所在节点    Go 编程语言
111 条回复
winglight2016
2023-11-03 11:28:45 +08:00
现在的 spring 已经超过当初的 EJB 多少倍了,哪里还有轻这个概念,IoC 也不是什么好事儿,严重降低代码的可阅读性。

函数式编程已经抛弃了 OOP 的封装,lz 又当成个宝捡回来。。。
mightybruce
2023-11-03 11:30:43 +08:00
我目前简单用用就用的是这个, 我自己还改过一些代码
https://github.com/shenyisyn/goft-ioc
yangzzz
2023-11-03 11:31:35 +08:00
一个疑问?既然要这么做为啥不用 java 去开发呢😅
mightybruce
2023-11-03 11:36:05 +08:00
我老大说过,写业务代码用这个其实就是用来方便控制人的。spring 让写代码的变得没有技术含量, 只关心业务。这个在 go 主力的中间件和云原生领域不好使。
limpo
2023-11-03 11:37:55 +08:00
@winglight2016 我同意你说的降低代码可读性,鱼和熊掌确实很难同时得到,至于函数式/OOP 之争也不是这几年才有的,虽然但是就个人开发体验来说还是挺好用的,至于路线之争也不会马上就出结果不是吗
limpo
2023-11-03 11:38:46 +08:00
@mightybruce 我先赞一个,后来学习一下~
FreeEx
2023-11-03 11:40:45 +08:00
lbp0200
2023-11-03 11:41:08 +08:00
万物皆可 spring ,等 PHP-spring ,Python-spring ,……
dilu
2023-11-03 11:42:41 +08:00
哥,求求你们这群 java 别来卷 Go 啊,因为我真的是做 Go 的啊 wuwuwu

我就想到点下班怎么就这么难啊 doge
limpo
2023-11-03 11:43:08 +08:00
@mightybruce 也许大部分的程序员工作内容也没有太多技术含量,这部分始终还是需要人去做不是吗,那我的工作就有意义了,go-spring 确实不是为中间件,基础库准备的,它是纯粹的业务框架,用来给堆业务代码的人提供方便。
limpo
2023-11-03 11:43:56 +08:00
@FreeEx wire 是代码是生成的方式,go-spring 是基于反射的方式,支持更多丰富的特性
limpo
2023-11-03 11:45:10 +08:00
@dilu 我不是 Javaer ,我是纯正 Gopher ,go-spring 就是为了让大家早点下班才推出的啊 😂
limpo
2023-11-03 11:46:36 +08:00
@lbp0200 有没有可能他们不叫 XX-spring 但是也实现了 spring 的思想呢
sadfQED2
2023-11-03 11:54:40 +08:00
我写过 2 年多 java ,现在写了 3 年多 go 。go 语言本身不支持注解那一套东西,go 的设计理念也不推崇 spring 那一套。

强行实现 java 那一套,我觉得纯粹是影响性能,恶心后续接手的人。
securityCoding
2023-11-03 11:56:50 +08:00
java 写了 5 年,go2 年 体验下来就是我再也不想写 spring 那套东西 , 代码这东西啊简单直观永远是最优解
mcfog
2023-11-03 11:56:53 +08:00
google wire 和 uber dig 按 XP 选一个就行
yangxiaopeipei
2023-11-03 12:00:01 +08:00
@lbp0200 php 用 laravel
limpo
2023-11-03 12:00:24 +08:00
@sadfQED2 go-spring 这一套机制只工作在初始化层,不至于影响性能
limpo
2023-11-03 12:01:31 +08:00
@securityCoding 但是不得不承认确实也带来很多方便,不然你看现在很多 javaer 离开 spring 都不知道怎么写程序了😂
limpo
2023-11-03 12:02:30 +08:00
@mcfog 要是他俩都看不上眼,也可以来瞧瞧 go-spring 哈,万一看对眼了呢 😀

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://tanronggui.xyz/t/988146

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX