如何在Golang中共享服务连接

huangapple go评论78阅读模式
英文:

How to share service connections in Golang

问题

我是你的中文翻译助手,以下是翻译的内容:

我对Go语言还不熟悉,正在查看Go语言的elastic库,在入门示例中,它说:“通常为应用程序创建一个客户端。”

这是什么意思?你是在main函数中创建一个客户端,然后以某种方式将其传递给带有context的函数吗?你是创建一个全局变量并将其分配给客户端,像这样吗?

var (
  client *elastic.Client
)

func a() {
  client.Search()
}

func main() {
  c, err := elastic.NewClient()
  client = c
}
英文:

I'm new to Go and looking at this the elastic library for go and in the Getting Started example it says "You typically create one client for your app."

What does that mean? Do you create a client in the your main function and somehow pass it to the functions with context? Do you create a global variable and assign it to the client, like this?

var (
  client *elastic.Client
)

func a() {
  client.Search()
}

func main() {
  c, err := elastic.NewClient()
  client = c
}

答案1

得分: 2

这涉及到了一个在Go语言中有点有争议的话题:依赖注入

与其他一些语言不同,我们通常不相信使用复杂的IOC容器、XML配置和基于反射的工具来处理这种情况。我只是遵循一些简单的原则:

  1. 应用程序包和组件应该明确地传递它们所依赖的所有内容。最好使用接口类型。如果我的web包需要一个数据库连接和一个elastic客户端,它可以有一个类似于Serve(addr string, db database.DB, client *elastic.Client)的函数,其中DB是我的应用程序的数据库的接口类型。

  2. main函数的工作主要是读取配置,创建所有共享组件,并将它们传递给各个组件:

     func main(){
       var config = readConfig() //flags, json, whatever
       var elastic = elastic.NewClient(config.whatever)
       var db = database.New(config.Connectionstring)
    
       //现在启动应用程序组件
       web.Serve(config.Addr, db, elastic)
     }
    

我发现这种模式有助于保持我的包分离但又可以互操作。我尽量避免在包级别使用变量,特别是对于需要在运行时更改的内容。

英文:

This gets into a topic that is kinda controversial in go: dependency injection.

Unlike some other languages, we don't usually believe in complicated IOC containers, xml config, and reflection based tools for this kind of thing. I merely follow a few simple principles:

  1. Application packages and components should have all of their dependencies passed to them explicitly. Preferably as an interface type. If my web package needs a database connection, and an elastic client, it may have a function like Serve(addr string, db database.DB, client *elastic.Client) where DB is an interface type for my application's db.

  2. The job of main is essentially to read configuration, create all shared components, and pass them to the various components:

     func main(){
       var config = readConfig() //flags, json, whatever
       var elastic = elastic.NewClient(config.whatever)
       var db = database.New(config.Connectionstring)
    
       //now start app components
       web.Serve(config.Addr, db, elastic)
     }
    

I find this pattern helps keep my packages separate yet inter-operable. I try to avoid package level variables for anything that needs to change from run to run.

答案2

得分: 1

我会创建一个特殊类型来保存这些对象。

type AppFactory struct {
  Client          *http.Client
  DatastoreClient *datastore.Client
  FileStorage     FileStorage
  DB              DB
}

或者你可以使用context.Context

type key int
const clientKey key = 0

func NewContext(ctx context.Context, client *elastic.Client) context.Context {
    return context.WithValue(ctx, clientKey, client)
}

func ClientFromContext(ctx context.Context) *elastic.Client {
    client := ctx.Value(clientKey).(*elastic.Client)
    return client
}

个人而言,我会使用context.Context,因为它是更通用的解决方案。

我认为使用全局变量不是一个好主意。很快它可能会成为一个问题。

英文:

I would create special type that holds these objects.

type AppFactory struct {
  Client          *http.Client
  DatastoreClient *datastore.Client
  FileStorage     FileStorage
  DB              DB
} 

or you can use context.Context

type key int
const clientKey key = 0

func NewContext(ctx context.Context, client *elastic.Client) context.Context {
    return context.WithValue(ctx, clientKey, client)
}

func ClientFromContext(ctx context.Context) *elastic.Client {
    client := ctx.Value(clientKey).(*elastic.Client)
    return client
}

Personally, I would use context.Context because it is more universal solution.

I don't think it is a good idea to use global variables.
Very quickly it can become a problem.

huangapple
  • 本文由 发表于 2017年5月10日 04:34:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/43879353.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定