Skip to content

Commit 1569e5b

Browse files
authored
feat(option/internaloption): add new EmbeddableAdapter option (#1787)
1 parent a7f08e2 commit 1569e5b

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

internal/kokoro/vet.sh

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ golint ./... 2>&1 | ( \
3737
grep -v "exported method MarshalStyle.JSONReader should have comment or be unexported" | \
3838
grep -v "UnmarshalJSON should have comment or be unexported" | \
3939
grep -v "MarshalJSON should have comment or be unexported" | \
40+
grep -v ".Apply should have comment or be unexported" | \
4041
grep -vE "\.pb\.go:" || true) | tee /dev/stderr | (! read)
4142

4243
staticcheck -go 1.9 ./... 2>&1 | ( \

option/internaloption/internaloption.go

+7
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,10 @@ type withCreds google.Credentials
134134
func (w *withCreds) Apply(o *internal.DialSettings) {
135135
o.InternalCredentials = (*google.Credentials)(w)
136136
}
137+
138+
// EmbeddableAdapter is a no-op option.ClientOption that allow libraries to
139+
// create their own client options by embedding this type into their own
140+
// client-specific option wrapper. See example for usage.
141+
type EmbeddableAdapter struct{}
142+
143+
func (*EmbeddableAdapter) Apply(_ *internal.DialSettings) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2022 Google LLC.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package internaloption_test
6+
7+
import (
8+
"context"
9+
"fmt"
10+
11+
"google.golang.org/api/option"
12+
"google.golang.org/api/option/internaloption"
13+
)
14+
15+
type config struct {
16+
i int
17+
}
18+
19+
type clientSpecificOption interface {
20+
option.ClientOption
21+
ApplyOpt(*config)
22+
}
23+
24+
func WithFavoriteNumber(i int) option.ClientOption {
25+
return &withFavoriteNumber{i: i}
26+
}
27+
28+
type withFavoriteNumber struct {
29+
internaloption.EmbeddableAdapter
30+
i int
31+
}
32+
33+
func (w *withFavoriteNumber) ApplyOpt(c *config) {
34+
c.i = w.i
35+
}
36+
37+
type Foo struct {
38+
i int
39+
}
40+
41+
func NewFoo(ctx context.Context, opts ...option.ClientOption) (*Foo, error) {
42+
var conf config
43+
for _, opt := range opts {
44+
if fooOpt, ok := opt.(clientSpecificOption); ok {
45+
fooOpt.ApplyOpt(&conf)
46+
}
47+
}
48+
// Pass options to internals for dialing. All client-specific options will
49+
// be no-ops.
50+
return &Foo{i: conf.i}, nil
51+
}
52+
53+
func (f *Foo) Number() int { return f.i }
54+
55+
func ExampleEmbeddableAdapter() {
56+
f, err := NewFoo(context.Background(), WithFavoriteNumber(42))
57+
if err != nil {
58+
// TODO: handle error
59+
}
60+
fmt.Println(f.Number())
61+
// Output: 42
62+
}

0 commit comments

Comments
 (0)