Skip to main content

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: