如何在Golang中共享服务连接

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
}

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.

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.