-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Customizing constructors
A client may need to be instantiated with API-specific configuration or have some API-specific behavior.
To support customizing client construction, client libraries support the implementation of an internal client constructor hook. This hook enables integration of API-specific configuration or behaviors directly into the client library constructor.
Given the following protobuf service:
service LibraryService {
...
}
The LibraryClient
has the following service-specific clientHook
:
var newLibraryClientHook clientHook
A clientHook
implementation that detects the presence of an emulator host
name in the environment might be as follows:
package library
import (
"context"
"os"
"google.golang.org/api/option"
"google.golang.org/grpc"
)
func init() {
newLibraryClientHook = func(ctx context.Context, p clientHookParams) ([]option.ClientOption, error) {
if emulator := os.Getenv("LIBRARY_EMULATOR_HOST"); emulator != "" {
return []option.ClientOption{
option.WithEndpoint(emulator),
option.WithGRPCDialOption(grpc.WithInsecure())
}, nil
}
return nil, nil
}
}
Each client library package has the same client hook type defined.
import (
"context"
"google.golang.org/api/option"
)
type clientHookParams struct{}
type clientHook func(context.Context, clientHookParams) ([]option.ClientOption, error)
A clientHook
receives a context.Context
and an instance of
clientHookParams
, and returns a option.ClientOption
slice.
The clientHookParams
type provides flexibility to the client hook
interface. As new use cases are discovered, more data can be made available to
clientHook
implementations through the clientHookParams
.
Note: both types are part of the generated client content and cannot be manually edited.
Each service client has a service-specific, package-level variable of type
clientHook
.
var newFooClientHook clientHook
Client owners can implement a clientHook
and assign it to one or many
service-specific clientHook
variables as needed.
At runtime during client construction, if a client hook variable is assigned
an implementation, it is invoked with the same Context
that was provided to
the constructor, and a clientHookParams
struct. Client hook invocation
occurs prior to connection dialing.
Options are applied in the following order:
- Default options.
-
clientHook
options. - User-supplied options.
So, user-supplied options have precedence over clientHook
options, which have
precedence over default options.
-
The
Context
given to theclientHook
must be used as is. It must not be copied and mutated. This is to preserve user management ofContext
. -
A
clientHook
must not explicitly usepanic
. -
A
clientHook
must not emit log messages. -
All
clientHook
implementation code must be unexported. -
A
clientHook
must not add new dependencies. -
Every
clientHook
implementation must have tests. -
The
clientHook
implementation should be in a file namedhook.go
.