Documentation
¶
Overview ¶
Package toggo provides a flexible and performant feature flag and A/B testing SDK for Go.
Toggo enables you to manage feature rollouts, conduct A/B tests, and control feature access with fine-grained targeting conditions. It supports:
- Simple on/off feature flags
- Percentage-based rollouts with deterministic hashing
- Complex conditional targeting (country, plan, custom attributes)
- A/B testing with multiple variants
- Thread-safe operations
- Configuration loading from JSON/YAML files
Basic Usage ¶
Create a store and add a feature flag:
store := toggo.NewStore()
flag := &toggo.Flag{
Name: "new_checkout",
Enabled: true,
Rollout: 50,
}
store.AddFlag(flag)
Check if a feature is enabled:
ctx := toggo.Context{
"user_id": "12345",
"country": "US",
}
if store.IsEnabled("new_checkout", ctx) {
// Use new checkout flow
}
A/B Testing ¶
For A/B testing with variants:
flag := &toggo.Flag{
Name: "pricing_test",
Enabled: true,
DefaultVariant: "control",
Variants: []toggo.Variant{
{Name: "control", Weight: 50},
{Name: "variant_a", Weight: 50},
},
}
store.AddFlag(flag)
variant, _ := store.GetVariant("pricing_test", ctx)
switch variant {
case "control":
// Original pricing
case "variant_a":
// New pricing
}
Conditional Targeting ¶
Add conditions to target specific users:
flag := &toggo.Flag{
Name: "premium_feature",
Enabled: true,
Rollout: 100,
Conditions: []toggo.Condition{
{
Attribute: "plan",
Operator: toggo.OperatorEqual,
Value: "premium",
},
{
Attribute: "country",
Operator: toggo.OperatorIn,
Value: []interface{}{"US", "CA", "UK"},
},
},
}
Loading from Configuration Files ¶
Load flags from JSON or YAML:
loader := loader.NewYAMLFile("flags.yaml")
loader.LoadIntoStore(store)
Operators ¶
Toggo supports various comparison operators:
- == (equal)
- != (not equal)
- in (value in list)
- not_in (value not in list)
- > (greater than)
- >= (greater than or equal)
- < (less than)
- <= (less than or equal)
- contains (string contains)
- starts_with (string starts with)
- ends_with (string ends with)
- regex (regular expression match)
Index ¶
- Constants
- Variables
- type Condition
- type Context
- type DefaultRolloutStrategy
- type Flag
- type Operator
- type RolloutStrategy
- type Store
- func (s *Store) AddFlag(flag *Flag) error
- func (s *Store) AddFlags(flags []*Flag) error
- func (s *Store) Clear()
- func (s *Store) GetFlag(name string) (*Flag, error)
- func (s *Store) GetRolloutStrategy() RolloutStrategy
- func (s *Store) GetVariant(name string, ctx Context) (string, bool)
- func (s *Store) GetVariantWithError(name string, ctx Context) (string, bool, error)
- func (s *Store) IsEnabled(name string, ctx Context) bool
- func (s *Store) IsEnabledWithError(name string, ctx Context) (bool, error)
- func (s *Store) ListFlags() []string
- func (s *Store) RemoveFlag(name string)
- func (s *Store) Size() int
- type StoreOption
- type SwitchbackInfo
- type SwitchbackOption
- type SwitchbackRolloutStrategy
- func (s *SwitchbackRolloutStrategy) GetCurrentDay() int
- func (s *SwitchbackRolloutStrategy) GetCurrentInterval() int
- func (s *SwitchbackRolloutStrategy) GetInfo() SwitchbackInfo
- func (s *SwitchbackRolloutStrategy) GetTimeUntilNextSwitch() time.Duration
- func (s *SwitchbackRolloutStrategy) GetVariant(flag *Flag, ctx Context) (string, error)
- func (s *SwitchbackRolloutStrategy) ShouldRollout(flag *Flag, ctx Context) (bool, error)
- func (s *SwitchbackRolloutStrategy) String() string
- type Variant
Constants ¶
const (
// Version is the current version of the toggo SDK
Version = "1.0.0"
)
Variables ¶
var ( // ErrFlagNotFound is returned when a requested flag doesn't exist in the store ErrFlagNotFound = errors.New("flag not found") // ErrInvalidOperator is returned when an unsupported operator is encountered ErrInvalidOperator = errors.New("invalid operator") // ErrInvalidRollout is returned when rollout percentage is not between 0 and 100 ErrInvalidRollout = errors.New("rollout must be between 0 and 100") // ErrInvalidCondition is returned when a condition is malformed ErrInvalidCondition = errors.New("invalid condition") // ErrRolloutKeyMissing is returned when the specified rollout key is not in context ErrRolloutKeyMissing = errors.New("rollout key missing from context") )
Functions ¶
This section is empty.
Types ¶
type Condition ¶
type Condition struct {
// Attribute is the key to lookup in the context
Attribute string `json:"attribute" yaml:"attribute"`
// Operator is the comparison operator to use
Operator Operator `json:"operator" yaml:"operator"`
// Value is the value to compare against (can be string, number, array, etc.)
Value interface{} `json:"value" yaml:"value"`
// Negate inverts the condition result if true
Negate bool `json:"negate,omitempty" yaml:"negate,omitempty"`
}
Condition represents a single evaluation condition
type Context ¶
type Context map[string]interface{}
Context represents the evaluation context containing arbitrary attributes used for feature flag evaluation. It can hold any key-value pairs such as user_id, country, plan, etc.
func (Context) Get ¶
Get retrieves a value from the context by key. Returns the value and a boolean indicating whether the key exists.
type DefaultRolloutStrategy ¶
type DefaultRolloutStrategy struct {
// contains filtered or unexported fields
}
DefaultRolloutStrategy implements standard percentage-based rollout
func NewDefaultRolloutStrategy ¶
func NewDefaultRolloutStrategy(hasher hash.Hasher) *DefaultRolloutStrategy
NewDefaultRolloutStrategy creates a new default rollout strategy
func (*DefaultRolloutStrategy) GetVariant ¶
func (r *DefaultRolloutStrategy) GetVariant(flag *Flag, ctx Context) (string, error)
GetVariant determines which variant to return based on weights
func (*DefaultRolloutStrategy) ShouldRollout ¶
func (r *DefaultRolloutStrategy) ShouldRollout(flag *Flag, ctx Context) (bool, error)
ShouldRollout determines if the flag should be enabled based on rollout percentage
type Flag ¶
type Flag struct {
// Name is the unique identifier for this flag
Name string `json:"name" yaml:"name"`
// Enabled controls whether this flag is active
Enabled bool `json:"enabled" yaml:"enabled"`
// Rollout is the percentage (0-100) of users who should see this flag
// when all conditions are met
Rollout int `json:"rollout,omitempty" yaml:"rollout,omitempty"`
// RolloutKey specifies which context attribute to use for rollout hashing
// Defaults to "user_id" if not specified
RolloutKey string `json:"rollout_key,omitempty" yaml:"rollout_key,omitempty"`
// Conditions are the rules that must ALL be satisfied for the flag to be enabled
Conditions []Condition `json:"conditions,omitempty" yaml:"conditions,omitempty"`
// Variants enables A/B testing with multiple variations
// If set, IsEnabled returns false and GetVariant should be used instead
Variants []Variant `json:"variants,omitempty" yaml:"variants,omitempty"`
// DefaultVariant is returned when no variant matches
DefaultVariant string `json:"default_variant,omitempty" yaml:"default_variant,omitempty"`
}
Flag represents a feature flag configuration
func (*Flag) GetRolloutKey ¶
GetRolloutKey returns the key to use for rollout hashing
func (*Flag) HasVariants ¶
HasVariants returns true if this flag has A/B test variants configured
type Operator ¶
type Operator string
Operator represents a comparison operator for condition evaluation
const ( // OperatorEqual checks if attribute equals value OperatorEqual Operator = "==" // OperatorNotEqual checks if attribute does not equal value OperatorNotEqual Operator = "!=" // OperatorIn checks if attribute is in a list of values OperatorIn Operator = "in" // OperatorNotIn checks if attribute is not in a list of values OperatorNotIn Operator = "not_in" // OperatorGreaterThan checks if attribute is greater than value OperatorGreaterThan Operator = ">" // OperatorGreaterThanOrEqual checks if attribute is greater than or equal to value OperatorGreaterThanOrEqual Operator = ">=" // OperatorLessThan checks if attribute is less than value OperatorLessThan Operator = "<" // OperatorLessThanOrEqual checks if attribute is less than or equal to value OperatorLessThanOrEqual Operator = "<=" // OperatorContains checks if attribute string contains value OperatorContains Operator = "contains" // OperatorStartsWith checks if attribute string starts with value OperatorStartsWith Operator = "starts_with" // OperatorEndsWith checks if attribute string ends with value OperatorEndsWith Operator = "ends_with" // OperatorRegex checks if attribute matches regex pattern OperatorRegex Operator = "regex" )
type RolloutStrategy ¶
type RolloutStrategy interface {
// ShouldRollout determines if a flag should be enabled based on rollout percentage
ShouldRollout(flag *Flag, ctx Context) (bool, error)
// GetVariant determines which variant to return for A/B testing
GetVariant(flag *Flag, ctx Context) (string, error)
}
RolloutStrategy defines how rollout decisions are made
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store manages feature flags and provides thread-safe evaluation
func (*Store) GetRolloutStrategy ¶
func (s *Store) GetRolloutStrategy() RolloutStrategy
GetRolloutStrategy returns the current rollout strategy This is useful for accessing strategy-specific features or for testing
func (*Store) GetVariant ¶
GetVariant returns the variant for A/B testing Returns the variant name and whether the flag is enabled
func (*Store) GetVariantWithError ¶
GetVariantWithError returns the variant with detailed error information
func (*Store) IsEnabled ¶
IsEnabled checks if a feature flag is enabled for the given context This is the primary method for simple on/off feature flags
func (*Store) IsEnabledWithError ¶
IsEnabledWithError checks if a feature flag is enabled and returns any error
func (*Store) RemoveFlag ¶
RemoveFlag removes a flag from the store
type StoreOption ¶
type StoreOption func(*Store)
StoreOption is a functional option for configuring the Store
func WithSwitchback ¶
func WithSwitchback(opts ...SwitchbackOption) StoreOption
WithSwitchback is a StoreOption that configures switchback testing
type SwitchbackInfo ¶
type SwitchbackInfo struct {
CurrentInterval int
CurrentDay int
TimeUntilSwitch time.Duration
IntervalDuration time.Duration
}
GetSwitchbackInfo returns detailed information about current switchback state
func GetSwitchbackInfo ¶
func GetSwitchbackInfo(store *Store) *SwitchbackInfo
GetSwitchbackInfo is a convenience method to get switchback info from a store Returns nil if the store is not using switchback strategy
type SwitchbackOption ¶
type SwitchbackOption func(*SwitchbackRolloutStrategy)
SwitchbackOption configures a switchback strategy
func WithDailySwap ¶
func WithDailySwap(enabled bool) SwitchbackOption
WithDailySwap enables swapping the variant order on alternating days Day 0: variants in order, Day 1: variants in reverse order, etc.
func WithIntervalMinutes ¶
func WithIntervalMinutes(minutes int) SwitchbackOption
WithIntervalMinutes sets the duration of each switchback interval in minutes
func WithStartTime ¶
func WithStartTime(t time.Time) SwitchbackOption
WithStartTime sets the reference start time for calculating intervals
type SwitchbackRolloutStrategy ¶
type SwitchbackRolloutStrategy struct {
// contains filtered or unexported fields
}
SwitchbackRolloutStrategy implements time-based switchback testing In switchback tests, all users see the same variant at the same time, and the variant switches at regular intervals
func NewSwitchbackRolloutStrategy ¶
func NewSwitchbackRolloutStrategy(opts ...SwitchbackOption) *SwitchbackRolloutStrategy
NewSwitchbackRolloutStrategy creates a new switchback rollout strategy
func (*SwitchbackRolloutStrategy) GetCurrentDay ¶
func (s *SwitchbackRolloutStrategy) GetCurrentDay() int
GetCurrentDay returns which day number we're in since start time
func (*SwitchbackRolloutStrategy) GetCurrentInterval ¶
func (s *SwitchbackRolloutStrategy) GetCurrentInterval() int
GetCurrentInterval returns which time interval we're currently in
func (*SwitchbackRolloutStrategy) GetInfo ¶
func (s *SwitchbackRolloutStrategy) GetInfo() SwitchbackInfo
GetInfo returns detailed switchback timing information
func (*SwitchbackRolloutStrategy) GetTimeUntilNextSwitch ¶
func (s *SwitchbackRolloutStrategy) GetTimeUntilNextSwitch() time.Duration
GetTimeUntilNextSwitch returns how much time until the next interval switch
func (*SwitchbackRolloutStrategy) GetVariant ¶
func (s *SwitchbackRolloutStrategy) GetVariant(flag *Flag, ctx Context) (string, error)
GetVariant returns the current variant based on time interval All users get the same variant at the same time
func (*SwitchbackRolloutStrategy) ShouldRollout ¶
func (s *SwitchbackRolloutStrategy) ShouldRollout(flag *Flag, ctx Context) (bool, error)
ShouldRollout always returns true for switchback tests since all users participate
func (*SwitchbackRolloutStrategy) String ¶
func (s *SwitchbackRolloutStrategy) String() string
String returns a human-readable description of the switchback state
type Variant ¶
type Variant struct {
// Name is the variant identifier
Name string `json:"name" yaml:"name"`
// Weight is the percentage (0-100) of traffic allocated to this variant
Weight int `json:"weight" yaml:"weight"`
// Conditions are additional conditions specific to this variant
Conditions []Condition `json:"conditions,omitempty" yaml:"conditions,omitempty"`
}
Variant represents an A/B test variant
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
ab_testing
command
|
|
|
abtest
command
|
|
|
basic
command
|
|
|
conditional
command
|
|
|
conditions
command
|
|
|
config_loader
command
|
|
|
simple
command
|
|
|
switchback
command
|
|
|
yaml_config
command
|
|
|
internal
|
|