Go-Spring v1.2.0 发布,新增 Web 开发支持

2023-12-08 15:38:27 +08:00
 limpo

Go-Spring v1.2.0 新增 web 服务器支持,底层路由器基于mux实现,旨在提供更加简单易用的开发体验。

特性:

支持绑定的函数形式 (将下列函数转换为 http.HandlerFunc ):

友情提示:web 包不依赖 go-spring 容器,可以单独使用 (下方有例子) 😀

Demo 代码:


package main

import (
	"context"
	"log/slog"
	"math/rand"
	"mime/multipart"
	"net/http"
	"time"

	"github.com/go-spring-projects/go-spring/gs"
	"github.com/go-spring-projects/go-spring/web"
	_ "github.com/go-spring-projects/go-spring/web/starter"
)

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

func (g *Greeting) OnInit(ctx context.Context) error {
	g.Server.Get("/greeting", g.Greeting)
	g.Server.Get("/health", g.Health)
	g.Server.Post("/user/register/{username}/{password}", g.Register)
	g.Server.Post("/user/password", g.UpdatePassword)
	return nil
}

func (g *Greeting) Greeting(ctx context.Context) string {
	web.FromContext(ctx).
		SetCookie("token", "1234567890", 500, "", "", false, false)
	return "greeting!!!"
}

func (g *Greeting) Health(ctx context.Context) error {
	if 0 == rand.Int()%2 {
		return web.Error(400, "health check failed")
	}
	return nil
}

func (g *Greeting) Register(
	ctx context.Context,
	req struct {
		Username  string                `path:"username" expr:"len($)>6 && len($)<20"`
		Password  string                `path:"password" expr:"len($)>6 && len($)<20"` 
		HeadImg   *multipart.FileHeader `form:"headImg"`                              
		Captcha   string                `form:"captcha" expr:"len($)==4"`              
		UserAgent string                `header:"User-Agent"`                          
		Ad        string                `query:"ad"`                                   
		Token     string                `cookie:"token"`                               
	},
) string {
	g.Logger.Info("register user",
		slog.String("username", req.Username),
		slog.String("password", req.Password),
		slog.String("userAgent", req.UserAgent),
		slog.String("headImg", req.HeadImg.Filename),
		slog.String("captcha", req.Captcha),
		slog.String("userAgent", req.UserAgent),
		slog.String("ad", req.Ad),
		slog.String("token", req.Token),
	)
	return "ok"
}

func (g *Greeting) UpdatePassword(
	ctx context.Context,
	req struct {
		Password string `json:"password" expr:"len($) > 6 && len($) < 20"` // password
		Token    string `cookie:"token"`                                   // token
	},
) string {
	g.Logger.Info("change password", slog.String("password", req.Password))
	return "ok"
}

func main() {
	gs.Object(new(Greeting))

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

单独使用 web 服务例子:

package main

import (
	"context"
	"log/slog"
	"mime/multipart"

	"github.com/go-spring-projects/go-spring/web"
)

func Greeting(ctx context.Context) string {
	return "Greeting!!!"
}

func Feedback(
	ctx context.Context,
	req struct {
		Title       string                  `form:"title"`        // 反馈标题
		Message     string                  `form:"message"`      // 反馈说明
		Attachments []*multipart.FileHeader `form:"files"`        // 上传附件文件列表
		EMail       string                  `form:"email"`        // 联系邮箱
		UserAgent   string                  `header:"User-Agent"` // 浏览器用户代理
	},
) string {
	slog.Info("received user feedback",
		slog.String("title", req.Title),
		slog.String("message", req.Message),
		slog.String("email", req.EMail),
		slog.String("user-Agent", req.UserAgent),
	)
	//TODO: save feedback to database.
	//
	return "Thanks for your feedback!!!"
}

func main() {
	webSvr := web.NewServer(web.NewRouter(), web.Options{Addr: ":8080"})
	webSvr.Get("/greeting", Greeting)
	webSvr.Post("/feedback", Feedback)

	webSvr.Run()
}

1467 次点击
所在节点    Go 编程语言
5 条回复
8520ccc
2023-12-08 21:29:37 +08:00
有木有群 要不要搞个群?有一些想法 可以交流一下

例如 绑定路由这里可以参考 goframe 那样。bind struct 使用 struct 上的方法

同时使用路径进行路由命名

例如

GET /v1/admin/user/fetch

可以是 /v1/admin/下的

v1_admin_user_fetch.go 的文件下面的

由 struct 上的 FetchGET 方法提供 ( goframe 是在 Input 的 struct 上定义这些)

其实这一套实现一个代码生成比较舒服。。。我现在自己搞了一套 但是不是很完善
8520ccc
2023-12-08 21:30:46 +08:00
还有直接绑定 interface

例如绑定

bind(controller.V1()) 这样就可以自动绑定所有 /v1/ 开头的全部路由

(当然前提也是需要提前生成好 V1 这个 interface )
DefoliationM
2023-12-08 22:41:39 +08:00
本来挺简单的一些东西,被这么一搞变难用了。
mightybruce
2023-12-09 14:47:25 +08:00
个人观点:非常不喜欢这种被限制的方式, 就算是 aop , 那么也要精简,而不是做全。
让 gin 、echo 、iris 能够接入就行,或者参考 kratos 做成插件形式。
limpo
2023-12-11 08:55:31 +08:00
@8520ccc 目前关注的人太少,所以没有群,要不直接加我 Q460229261

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

https://www.v2ex.com/t/998718

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

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

© 2021 V2EX