binder
packageAPI reference for the binder
package.
Imports
(5)HandlerFunc
HandlerFunc is a function that handles binding a set of string arguments to a field.
type HandlerFunc func(args []string) error
Binder
Binder handles mapping and execution of field bindings.
type Binder struct
Methods
Handlers returns the registered handlers.
Returns
func (*Binder) Handlers() map[string]HandlerFunc
{
return b.handlers
}
AddBool registers a custom handler for a boolean field.
Parameters
func (*Binder) AddBool(key string, fn func(bool) error)
{
b.handlers[key] = func(args []string) error {
var val bool
if len(args) > 0 {
fmt.Sscanf(args[0], "%t", &val)
} else {
val = true
}
return fn(val)
}
}
AddInt registers a custom handler for an integer field.
Parameters
func (*Binder) AddInt(key string, fn func(int64) error)
{
b.handlers[key] = func(args []string) error {
if len(args) == 0 {
return fmt.Errorf("missing value for %s", key)
}
var val int64
if _, err := fmt.Sscanf(args[0], "%d", &val); err != nil {
return err
}
return fn(val)
}
}
AddStrings registers a custom handler for a string slice field.
Parameters
func (*Binder) AddStrings(key string, fn func([]string) error)
{
b.handlers[key] = fn
}
Run executes the handler for the given key with the provided arguments.
Parameters
Returns
func (*Binder) Run(key string, args []string) error
{
b.hooks.runBefore(key, args)
h, ok := b.handlers[key]
if !ok {
return fmt.Errorf("no handler for key: %s", key)
}
if err := h(args); err != nil {
return err
}
b.hooks.runAfter(key, args)
return nil
}
BeforeHook registers a function to be called before a specific key is handled.
Parameters
func (*Binder) BeforeHook(key string, fn HookFunc)
{
b.hooks.addBefore(key, fn)
}
AfterHook registers a function to be called after a specific key is handled.
Parameters
func (*Binder) AfterHook(key string, fn HookFunc)
{
b.hooks.addAfter(key, fn)
}
AutoDiscover reflects on the destination struct to register default handlers.
Returns
func (*Binder) AutoDiscover() error
{
v := reflect.ValueOf(b.dst)
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
return fmt.Errorf("binder: destination must be a pointer to a struct")
}
elem := v.Elem()
typ := elem.Type()
for i := 0; i < elem.NumField(); i++ {
field := elem.Field(i)
fieldType := typ.Field(i)
tag := fieldType.Tag.Get("flag")
if tag == "" {
continue
}
params := ParseTag(tag)
long := params["long"]
if long == "" {
long = strings.ToLower(fieldType.Name)
}
// Register default handler if not already registered
if _, ok := b.handlers[long]; !ok {
b.RegisterDefaultHandler(field, long)
}
}
return nil
}
Parameters
func (*Binder) RegisterDefaultHandler(field reflect.Value, name string)
{
switch field.Kind() {
case reflect.Bool:
b.handlers[name] = func(args []string) error {
if len(args) > 0 {
var val bool
fmt.Sscanf(args[0], "%t", &val)
field.SetBool(val)
} else {
field.SetBool(true)
}
return nil
}
case reflect.String:
b.handlers[name] = func(args []string) error {
if len(args) > 0 {
field.SetString(args[0])
}
return nil
}
case reflect.Int, reflect.Int64:
b.handlers[name] = func(args []string) error {
if len(args) > 0 {
var val int64
fmt.Sscanf(args[0], "%d", &val)
field.SetInt(val)
}
return nil
}
}
}
AddDuration registers a custom handler for a duration field.
Parameters
func (*Binder) AddDuration(key string, fn func(time.Duration) error)
{
b.handlers[key] = func(args []string) error {
if len(args) == 0 {
return fmt.Errorf("missing value for %s", key)
}
val, err := time.ParseDuration(args[0])
if err != nil {
return err
}
return fn(val)
}
}
AddEnum registers a handler that validates against a set of allowed values.
Parameters
func (*Binder) AddEnum(key string, choices []string, fn func(string) error)
{
b.handlers[key] = func(args []string) error {
if len(args) == 0 {
return fmt.Errorf("missing value for %s", key)
}
val := args[0]
found := slices.Contains(choices, val)
if !found {
return fmt.Errorf("invalid value %s for %s, allowed: %v", val, key, choices)
}
return fn(val)
}
}
Fields
| Name | Type | Description |
|---|---|---|
| dst | any | |
| handlers | map[string]HandlerFunc | |
| hooks | *hooks |
NewBinder
NewBinder creates a new binder for the destination object.
Parameters
Returns
func NewBinder(dst any) (*Binder, error)
{
b := &Binder{
dst: dst,
handlers: make(map[string]HandlerFunc),
hooks: newHooks(),
}
if err := b.AutoDiscover(); err != nil {
return nil, err
}
return b, nil
}
ParseTag
Parameters
Returns
func ParseTag(tag string) map[string]string
{
params := make(map[string]string)
parts := strings.Split(tag, ",")
for _, part := range parts {
kv := strings.Split(part, ":")
if len(kv) == 2 {
params[strings.TrimSpace(kv[0])] = strings.TrimSpace(kv[1])
} else {
// Support flags without keys as long names (e.g. `flag:"verbose"`)
key := strings.TrimSpace(part)
if !strings.Contains(tag, ":") {
params["long"] = key
}
}
}
return params
}
HookFunc
HookFunc is a function called before or after a value is bound.
type HookFunc func(key string, args []string)
hooks
type hooks struct
Methods
Parameters
func (*hooks) addBefore(key string, fn HookFunc)
{
h.before[key] = append(h.before[key], fn)
}
Parameters
func (*hooks) addAfter(key string, fn HookFunc)
{
h.after[key] = append(h.after[key], fn)
}
Parameters
func (*hooks) runBefore(key string, args []string)
{
for _, fn := range h.before[key] {
fn(key, args)
}
}
Parameters
func (*hooks) runAfter(key string, args []string)
{
for _, fn := range h.after[key] {
fn(key, args)
}
}
Fields
| Name | Type | Description |
|---|---|---|
| before | map[string][]HookFunc | |
| after | map[string][]HookFunc |
newHooks
Returns
func newHooks() *hooks
{
return &hooks{
before: make(map[string][]HookFunc),
after: make(map[string][]HookFunc),
}
}