分享
  1. 首页
  2. 文章

用 Go 写一个服务容器( Service Container )

jzhongming · · 5643 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

我最近一直在做一个相当大的 API 项目,里面包括很多路由规则( routes )、服务接口( services )和处理函数( handlers )等。首先,我注意到 `main.go` 文件的启动过程开始越来越臃肿。 为了避免设置全局的服务接口,我使用共享结构体( struct )将服务接口与处理函数绑定在一起。举个例子: main.go ```go package main func main() { r := gin.Default() userRepo := models.NewUserRepo( drives.DataStore().C("users"), ) userHandler := handlers.NewUserHandler(userRepo) r.GET("/api/v1/users", userHandler.FindAll) r.Run(":8080") } ``` user_handler.go ```go type UserHandler struct { userRepo *models.UserRepo } func NewUserHandler(userRepo *models.UserRepo) *UserHandler { return &UserHandler{ userRepo, } } func (userHandler *UserHandler) FindAll(c *gin.Context) { users, err := userHandler.userRepo.FindAll() if err != nil { c.JSON(404, nil) return } c.JSON(200, users) return } ``` 这些代码工作的很好,但是,你会发现 main.go 中,我只是写了很少的启动过程,仅仅包含一个处理函数和一个持久化数据( repository )。(译注:用这种方式写代码比较麻烦且臃肿)。 于是我想用 Go 写一个容器。我找不到一个喜欢的第三方库来解决这个事情。所以,想出了下面这段代码。 ```go import( "sync" ) type Container struct{ mux sync.RWMutex m map[string]interface{} } // Add service func (c *Container) Add(name string, object interface{}) { c.mux.Lock() if c.m == nil { c.m = make(map[string]interface{}) } c.m[name] = object c.mux.Unlock() } // Remove service func (c *Container) Remove(name string) Container { c.mux.Lock() delete(c.m, name) c.mux.Unlock() } // Get a service func (c *Container) Get(name string) (object interface{}, bool) { c.mux.RLock() object, ok = c.m[name] c.mux.RUnlock() return object, ok } ``` 注意这段代码的每个方法都用了 `mutex lock` 来避免容器的并发问题。 现在代码可以这样写。。。 ```go func GetContainer() Container { c := new(container.Container) c.Add("user.handler", handlers.UserHandler) return c } ``` 现在的 main.go ```go func main() { container := container.GetContainer() userHandler, ok := container.Get("user.handler") if !ok { log.Fatal("Service not found") } r.GET( "/api/v1/users", userHandler.(*handlers.UserHandler).FindAll(), ) } ``` _同步方面的代码参考自 itsmontoya ,向他致敬_ 现在我已经将启动过程很简洁地封装成了包。我觉得一个有 PHP 语言背景的人在考虑这段语法实现时候会参考 [pimple](http://pimple.sensiolabs.org/) 框架。 我已经把这个抽象成了自己的库,实现在[这里](https://github.com/EwanValentine/Vertebrae) 。

via: https://ewanvalentine.io/writing-a-service-container-in-go/

作者:Ewan Valentine 译者:jzhongming 校对:rxcai

本文由 GCTT 原创编译,Go语言中文网 荣誉推出

本文由 GCTT 原创翻译,Go语言中文网 首发。也想加入译者行列,为开源做一些自己的贡献么?欢迎加入 GCTT!
翻译工作和译文发表仅用于学习和交流目的,翻译工作遵照 CC-BY-NC-SA 协议规定,如果我们的工作有侵犯到您的权益,请及时联系我们。

欢迎遵照 CC-BY-NC-SA 协议规定 转载,敬请在正文中标注并保留原文/译文链接和作者/译者等信息。
文章仅代表作者的知识和看法,如有不同观点,请楼下排队吐槽


有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
5643 次点击
被以下专栏收入,发现更多相似内容
6 回复 | 直到 2019年01月09日 21:48:30
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏