受 PHP 框架 Laravel 的启发, GoGym 兼顾了代码的简洁易用性 框架解决的需求是
示例代码:
type IndexController struct {
}
func (IndexController *IndexController) Index(values url.Values, headers http.Header) (statusCode int, response interface{}) {
return 200, map[string]string{"hello": "world"}
}
func main() {
var apiService = GoGym.Prepare()
apiService.Get("/", "IndexController@Index")
apiService.RegisterController(&IndexController{})
apiService.Serve(3000)
}
可以看到,我们只需要上面短短的 11 行代码,就能起一个 hello world 的 RESTful 服务
欢迎大家发 issue 或者邮件来讨论不足的地方,让我可以改进,也可以提交 feature requirement ,如果觉得不错也欢迎 star
项目地址: https://github.com/ZhenhangTung/GoGym
八卦一下,起这个项目名字就是因为自己喜欢去健身房,对自己也是一种督促,也希望大家多多运动保重身体,敲代码是产出的话,休息运动就是给自己充值了。
共勉!
Notice: 我已经将GoGym中的功能一个个拆分,作为服务的存在,并定义了服务的接口,还开放了RegisterService()来支持用户注册自己定义的服务到Service Container中,这对于初始的版本是个重大的改变。但由于Go的语言特性,对于用户注册的服务,调用方法会使用到reflcet,我也提供了一个helper方法CallMethod()来实现调用,如果用户想自己写也没有问题。
示例代码如下:
package main
import (
"fmt"
"github.com/ZhenhangTung/GoGym"
"net/http"
"reflect"
)
type HelloController struct {
}
func (h *HelloController) SayHello(api *GoGym.Gym) {
api.Response.JsonResponse(map[string]string{"hello": "world"}, 200, http.Header{})
}
type FooService struct {
boss *GoGym.Gym
}
func (f *FooService) Prepare(g *GoGym.Gym) {
f.WhoIsYourBoss(g)
}
func (f *FooService) WhoIsYourBoss(g *GoGym.Gym) {
f.boss = g
}
func (f *FooService) CallYourBoss() *GoGym.Gym {
return f.boss
}
func (f *FooService) Test() {
fmt.Println("oh yes")
}
func (f *FooService) CallMethod(method string, param []interface{}) []reflect.Value {
r := GoGym.CallServiceMethodWithReflect(f, method, param)
return r
}
func main() {
var gym = new(GoGym.Gym)
gym.Prepare()
gym.Router.RegisterController(&HelloController{})
gym.Router.Get("/", "HelloController@SayHello")
gym.RegisterService("Foo", new(FooService))
gym.GetService("Foo").CallMethod("Test", nil)
gym.OpenAt(3000)
}
具体详情还请移步去看项目的文档。 感谢!
1
taowen 2017-03-14 08:52:13 +08:00
支持一下,造轮子不容易
|
3
jarlyyn 2017-03-15 15:56:27 +08:00
看不懂。
这是要注册个 controller 类,实现 controller interface ? 直接用 httprouter 就可以了啊 var jsonAction = func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { body, _ := json.Marshal(map[string]string{"hello": "world"}) w.Write(body) } router := httprouter.New() router.RedirectTrailingSlash = false router.RedirectFixedPath = false router.GET("/test", jsonAction) http.Handle("/controller/", http.StripPrefix("/controller", router)) http.ListenAndServe(":3000", http.DefaultServeMux) |
4
jarlyyn 2017-03-15 16:10:36 +08:00
要说看得出来的问题的话,感觉以字符串形式传 action 太坑
及不能类型检测,不能错误检查。 |
5
leontung OP @jarlyyn 十分感谢!我之前都没发现有 router 这么厉害的项目。
我是在学习过程中,发现 Golang 很多 web 框架,比如 echo 等,都会先预定好一些方法( Action ),比如在 Controller(有些框架定义为 router)中有 GET , POST 等方法来接收 GET 和 POST 等请求,这样很不错,也符合 Golang 的语言特性,但我觉得不太能满足业务需求,如果我有一个 Controller ,就是负责首页逻辑的,需要接收 2 个 GET 方法,按照目前我的理解来看,我就要创建两个 controller 了。 我解决的事情是,只需要建立一个 Controller ,下面可以定义无数个 Action 。 用 apiService.Get("/", "IndexController@Index")注册了后,在底层就会生成一个包含 http request , route , Controller , Action 的 map ,最后我用的是 reflect 去调用所有的 Action 。 你提到的类型检测,不能错误检查这两点我会考虑并且看看怎么加入。 |
6
jarlyyn 2017-03-15 23:51:01 +08:00
@leontung
一个 router 就是一个控制器。 想一想,写 web 为什么一定要有控制器类呢? 方法 /函数本身就可以作为变量,所以其实不一定需要控制器类这个概念。 还有就是。 要代码补全的话,直接吧 action 传进去就可以了。 比如 indexController:=&IndexController{} apiService.Get("/", indexCroller.index) |
7
jarlyyn 2017-03-15 23:53:34 +08:00
@leontung
以我的 blog 为例 https://gist.github.com/jarlyyn/57ac8e2dc950e9c7715de27149481319 用了两个 router 其实不就等于是两个控制器? |
8
leontung OP @jarlyyn 的确没有任何规定要规定大家都用 controller class ,然后在里面定义一系列 method 作为 action 来开发项目呢,就像写代码也不一定要用 OOP 思想来写。这些思想需要我们在某些前提下讨论。
如果我写一个小项目(我觉得自己的个人博客也算其中之一吧),或者小脚本,不管是 golang , php 还是 js ,以我目前的浅薄的开发经验,都不需要建立 class ( Golang 里是 struct ),搞个 class 来有时甚至只是种累赘。 但如果我们的项目发展到一定程度了呢,有同事朋友或者其他开发者参与进来了呢,考虑的不只是实现了,我们还要考虑 organization ,往大一点说就是架构,考虑他人的开发感受,我认为这就是会有各种设计模式的原因吧,大家在同一个 convention 下开发(注意,我没有用 law 这个词)。 我的小项目目标是“ RESTful API ”。 扯开点说,代码除了代码本身的语法和规定,怎么写都是大家自己的决定, free style 都可以,只是在每个情景之下都会有 pros&cons ,是适合不适合的问题,并没有对错。 --- 我:PHP 是世界上最好的语言,不是吗? A:Java 才是 B:Bullshit! .... 2333~ |
9
jarlyyn 2017-03-16 11:59:54 +08:00
@leontung
middleware 本身就是一种组织形式啊。 不过是组件化 Vs 继承罢了。 从某种角度来说,使用控制器类并不一定适合,或者从我的经验来看不适合大规模的项目。大项目最简单的降低难度的方式就是拆散。调试 /继承中间件在这个情况下比调整控制器类容易的多。 当然,这点并不重要。我只是一些建议和意见罢了。 我只是在写了几年 php 后歪到 nodejs 去了,受 express/koa 影响多了,觉得 middleware 型的框架水到渠成罢了。 |
10
leontung OP @jarlyyn 嗯嗯,理解,你的建议很棒,我自己已经开好了 issue 着手改造了。
我是写了 PHP 最近因为公司业务需求歪到了 Golang 哈哈哈。 |
11
leontung OP @jarlyyn middleware 我还不是特别熟悉,在 laravel5 引入了 middleware 时候我一直在用 Phalcon 写业务,没有机会去学,我去调研学习一下这个概念
|
12
102400 2017-04-10 02:29:37 +08:00
Laravel 本身比很多 web 框架都要麻烦复杂得多,用它的方式写 go 还不如不要
|