func (f *fields) get(key bindKey) (reflect.Value, bool) {
	f.RLock()
	value, ok := f.m[key]
	f.RUnlock()
	return value, ok
}
get retrieves the value bound to key.
package modules
import (
	"errors"
	"fmt"
	"reflect"
	"sync"
	"github.com/go-modules/modules/tags"
)
func newBinding(binder *Binder) *binding {
	return &binding{
		binder,
		fields{m: make(map[bindKey]reflect.Value)},
		gates{m: make(map[bindKey]gate)},
		newGate(),
		make(chan error),
	}
}
type binding struct {
	*Binder
	fields
	gates
	cancel gate
	errors chan error
}
func (b *binding) inject(bindName string, value reflect.Value) {
	key := bindKey{value.Type(), bindName}
	select {
	case <-b.cancel:
		b.logf("nothing bound to %s\n", key.String())
	case <-b.gates.get(key):
		if bound, ok := b.fields.get(key); ok {
			value.Set(bound)
			b.logf("%v <- %s\n", bound, key.String())
		} else {
			b.logf("nothing bound to %s\n", key.String())
		}
	}
}
func (b *binding) provide(bindName string, singleton bool, tag tags.StructTag, value reflect.Value) error {
	key := bindKey{value.Type(), bindName}
	tag.ForEach(tags.Handler(func(tagKey, v string) (bool, error) {
		if tagKey == "provide" {
			return false, nil
		}
		if tagKey == "inject" {
			return false, errors.New(fmt.Sprintf("failed to parse tags for value %s ;a module field tagged with 'provide' cannot also be tagged with 'inject'", key))
		}
		if injector, ok := b.injectors[tagKey]; ok {
			if ok, err := injector.Inject(value, v); err != nil {
				return false, &AnnotatedError{msg: fmt.Sprintf("failed to provide value for %s from tag key %s", key, tagKey), cause: err}
			} else if ok {
				return true, nil
			} else {
				return false, nil
			}
		} else {
			return false, nil
		}
	}))
	var toBind reflect.Value
	if singleton && value.Kind() == reflect.Func && !value.IsNil() {
		toBind = asSingleton(value)
		b.logf("singleton(%v) -> %v -> %s\n", value, toBind, key)
	} else {
		toBind = value
		b.logf("%v -> %s\n", value, key)
	}
	b.fields.bind(key, toBind)
	close(b.gates.get(key))
	return nil
}
type fields struct {
	sync.RWMutex
	m map[bindKey]reflect.Value
}