Go
Install the latest version
go get github.com/prefab-cloud/prefab-cloud-go@latest
Initialize Client
Add prefab "github.com/prefab-cloud/prefab-cloud-go/pkg"
to your imports.
Then, initialize the client with your API key:
client, err := prefab.NewClient(prefab.WithAPIKey(apiKey))
Feature Flags
For boolean flags, you can use the FeatureIsOn
function:
enabled, ok := client.FeatureIsOn("my.feature.name", prefab.ContextSet{})
Flags that don't exist yet are considered off, so you can happily add FeatureIsOn
checks to your code before the flag is created.
Feature flags don't have to return just true or false.
You can get other data types using Get*
functions:
value, ok, err := client.GetStringValue("my.string.feature.name", prefab.ContextSet{})
value, ok, err := client.GetJSONValue("my.json.feature.name", prefab.ContextSet{})
Context
Feature flags become more powerful when we give the flag evaluation rules more information to work with. We do this by providing context of the current user (and/or team, request, etc.)
Global Context
When initializing the client, you can set a global context that will be used for all evaluations.
globalContext := prefab.NewContextSet().
WithNamedContextValues("host", map[string]interface{}{
"name": os.Getenv("HOSTNAME"),
"region": os.Getenv("REGION"),
"cpu": runtime.NumCPU(),
})
client, err := prefab.NewClient(
prefab.WithAPIKey(apiKey),
prefab.WithGlobalContext(globalContext),
)
Global context is the least specific context and will be overridden by more specific context passed in at the time of evaluation.
Bound Context
To make the best use of Prefab in a web setting, we recommend setting context per-request. Setting this context for the life-cycle of the request means the Prefab logger can be aware of your user/etc. for feature flags and targeted log levels and you won't have to explicitly pass context into your .FeatureIsOn
and .Get*
calls.
requestContext := prefab.NewContextSet().
WithNamedContextValues("user", map[string]interface{}{
"name": currentUser.GetName(),
"email": currentUser.GetEmail(),
})
boundClient := client.WithContext(requestContext)
enabled, ok := boundClient.FeatureIsOn("my.feature.name", prefab.ContextSet{})
Just-in-time Context
You can also pass context when evaluating individual flags or config values.
enabled, ok := boundClient.FeatureIsOn("my.feature.name", prefab.NewContextSet().
WithNamedContextValues("team", map[string]interface{}{
"name": currentTeam.GetName(),
"email": currentTeam.GetEmail(),
}))
Dynamic Config
Config values are available via the Get*
functions:
value, ok, err := client.GetJSONValue("slack.bot.config", prefab.ContextSet{})
value, ok, err := client.GetStringValue("some.string.config", prefab.ContextSet{})
value, ok, err := client.GetFloatValue("some.float.config", prefab.ContextSet{})
Default Values for Configs
Here we ask for the value of a config named max-jobs-per-second
, and we specify 10
as a default value if no value is available.
value, wasFound := client.GetIntValueWithDefault("max-jobs-per-second", 10, prefab.ContextSet{})
If max-jobs-per-second
is available, wasFound
will be true
and value
will be the value of the config. If max-jobs-per-second
is not available, wasFound
will be false
and value
will be 10
.
Testing
You can use a datafile for consistency, reproducibility, and offline testing. See Testing with DataFiles.
If you need to test multiple scenarios that depend on a single config or feature key, you can change set up a client with in-memory configs:
configs := map[string]interface{}{
"string.key": "value",
"int.key": int64(42),
"bool.key": true,
"float.key": 3.14,
"slice.key": []string{"a", "b", "c"},
"json.key": map[string]interface{}{
"nested": "value",
},
}
client, err := prefab.NewClient(prefab.WithConfigs(configs))
Notable pending features
The following notable features are still in-progress for the Go client:
- Telemetry
- Editor Tools support