예제 #1
0
func TemplateVars(typ interface{}) template.VarMap {
	fin := []reflect.Type{reflect.TypeOf(typ)}
	stringOut := []reflect.Type{reflect.TypeOf("")}
	stringFuncTyp := reflect.FuncOf(fin, stringOut, false)
	varFunc := func(in []reflect.Value) []reflect.Value {
		url, _ := updatesURL(in[0])
		return []reflect.Value{reflect.ValueOf(url)}
	}
	boolOut := []reflect.Type{reflect.TypeOf(true)}
	boolFuncTyp := reflect.FuncOf(fin, boolOut, false)
	enabledFunc := func(in []reflect.Value) []reflect.Value {
		url, _ := updatesURL(in[0])
		enabled := url != ""
		return []reflect.Value{reflect.ValueOf(enabled)}
	}
	template.AddFunc(&template.Func{
		Name:   "__gondola_is_live_reload_enabled",
		Fn:     reflect.MakeFunc(boolFuncTyp, enabledFunc).Interface(),
		Traits: template.FuncTraitContext,
	})
	reasonFunc := func(in []reflect.Value) []reflect.Value {
		_, reason := updatesURL(in[0])
		return []reflect.Value{reflect.ValueOf(reason)}
	}
	template.AddFunc(&template.Func{
		Name:   "__gondola_is_live_reload_disabled_reason",
		Fn:     reflect.MakeFunc(stringFuncTyp, reasonFunc).Interface(),
		Traits: template.FuncTraitContext,
	})

	return template.VarMap{
		"BroadcasterWebsocketUrl": reflect.MakeFunc(stringFuncTyp, varFunc).Interface(),
	}
}
예제 #2
0
파일: mock.go 프로젝트: ninjadq/eru-agent
func MakeMockedWrapper(fptr interface{}) {
	var maker = func(in []reflect.Value) []reflect.Value {
		wrapper := in[0].Elem()
		client := in[1]
		wrapperType := wrapper.Type()
		for i := 1; i < wrapperType.NumField(); i++ {
			field := wrapper.Field(i)
			fd, ok := client.Type().MethodByName(wrapperType.Field(i).Name)
			if !ok {
				logs.Info("Reflect Failed")
				continue
			}
			fdt := fd.Type
			f := reflect.MakeFunc(field.Type(), func(in []reflect.Value) []reflect.Value {
				ret := make([]reflect.Value, 0, fdt.NumOut())
				for i := 0; i < fdt.NumOut(); i++ {
					ret = append(ret, reflect.Zero(fdt.Out(i)))
				}
				return ret
			})
			field.Set(f)
		}
		return []reflect.Value{in[0]}
	}
	fn := reflect.ValueOf(fptr).Elem()
	v := reflect.MakeFunc(fn.Type(), maker)
	fn.Set(v)
}
예제 #3
0
파일: recover.go 프로젝트: sjn1978/go-fuzz
func test16() {
	defer mustRecover(16)

	f2 := reflect.MakeFunc(reflect.TypeOf((func(func()))(nil)), reflectFunc2).Interface().(func(func()))
	f3 := reflect.MakeFunc(reflect.TypeOf((func())(nil)), reflectFunc3).Interface().(func())
	defer f2(f3)

	panic(16)
}
예제 #4
0
파일: kvs.go 프로젝트: rainycape/gondola
// Funcs allows creating functions for easily setting and retrieving
// values associated with a key from an Storage in a type safe manner.
//
// Getter functions must conform to the following specification:
//
//  func(storage S, key interface{}) V or func(storage S, key interface{}) (V, bool)
//
// Where S is kvs.Storage or implements kvs.Storage and V is any type.
//
// Setter functions must conform to the following specification:
//
//  func(storage S, key interface{}, value V)
//
// Where V is any type. Note that when generating a getter/setter function pair,
// V must be exactly the same type in the getter and in the setter.
//
// See the examples for more information.
//
// Note that this function will panic if the prototypes of the functions don't,
// match the expected ones.
//
// Alternatively, if you're only going to store once value per type, use
// TypeFuncs instead.
func Funcs(getter interface{}, setter interface{}) {
	gptr := reflect.ValueOf(getter)
	if gptr.Kind() != reflect.Ptr || gptr.Elem().Kind() != reflect.Func {
		panic(fmt.Errorf("getter must be a pointer to a function, not %v",
			gptr.Type()))
	}
	gval := gptr.Elem()
	gvalType := gval.Type()
	if gvalType.NumIn() != 2 {
		panic(fmt.Errorf("getter must accept two arguments, not %d",
			gvalType.NumIn()))
	}
	if !isStorageType(gvalType.In(0)) {
		panic(fmt.Errorf("getter 1st argument must be of type %v or assignable to it, not %v",
			storageType, gvalType.In(0)))
	}
	if gvalType.In(1) != emptyInterfaceType {
		panic(fmt.Errorf("getter 2nd argument must be of type %v, not %v",
			emptyInterfaceType, gvalType.In(1)))
	}
	if gvalType.NumOut() != 1 {
		panic(fmt.Errorf("getter must return only one value, not %d",
			gvalType.NumOut()))
	}
	ttype := gvalType.Out(0)
	gval.Set(reflect.MakeFunc(gvalType, storageGetKey(ttype)))

	sptr := reflect.ValueOf(setter)
	if sptr.Kind() != reflect.Ptr || sptr.Elem().Kind() != reflect.Func {
		panic(fmt.Errorf("setter must be a pointer to a function, not %v",
			sptr.Type()))
	}
	sval := sptr.Elem()
	svalType := sval.Type()
	if svalType.NumIn() != 3 {
		panic(fmt.Errorf("setter must accept three arguments, not %d",
			svalType.NumIn()))
	}
	if !isStorageType(svalType.In(0)) {
		panic(fmt.Errorf("setter's 1st argument must be of type %v or assignable to it, not %v",
			storageType, svalType.In(0)))
	}
	if svalType.In(1) != emptyInterfaceType {
		panic(fmt.Errorf("setter's 2nd argument must be of type %v, not %v",
			emptyInterfaceType, svalType.In(1)))
	}
	if svalType.In(2) != ttype {
		panic(fmt.Errorf("setter's 3rd argument must be of type %v (to match getter), not %v",
			ttype, svalType.In(2)))
	}
	if svalType.NumOut() != 0 {
		panic(fmt.Errorf("setter not return any values, not %d",
			svalType.NumOut()))
	}
	sval.Set(reflect.MakeFunc(svalType, storageSetKey))
}
예제 #5
0
파일: gospy.go 프로젝트: cfmobile/gospy
func (self *GoSpy) setTargetFn(fn func(args []reflect.Value) []reflect.Value) {
	targetType := self.mock.GetTarget().Type()
	wrapperFn := func(args []reflect.Value) []reflect.Value {
		self.storeCall(args)
		return reflect.MakeFunc(targetType, fn).Call(args)
	}

	targetFn := reflect.MakeFunc(targetType, wrapperFn)
	self.mock.Replace(targetFn.Interface())
}
예제 #6
0
func makeSum(fptr interface{}) {
	fn := reflect.ValueOf(fptr).Elem()

	v := reflect.MakeFunc(fn.Type(), sum)

	fn.Set(v)
}
예제 #7
0
파일: trace.go 프로젝트: achanda/go
// compose modifies t such that it respects the previously-registered hooks in old,
// subject to the composition policy requested in t.Compose.
func (t *ClientTrace) compose(old *ClientTrace) {
	if old == nil {
		return
	}
	tv := reflect.ValueOf(t).Elem()
	ov := reflect.ValueOf(old).Elem()
	structType := tv.Type()
	for i := 0; i < structType.NumField(); i++ {
		tf := tv.Field(i)
		hookType := tf.Type()
		if hookType.Kind() != reflect.Func {
			continue
		}
		of := ov.Field(i)
		if of.IsNil() {
			continue
		}
		if tf.IsNil() {
			tf.Set(of)
			continue
		}

		// Make a copy of tf for tf to call. (Otherwise it
		// creates a recursive call cycle and stack overflows)
		tfCopy := reflect.ValueOf(tf.Interface())

		// We need to call both tf and of in some order.
		newFunc := reflect.MakeFunc(hookType, func(args []reflect.Value) []reflect.Value {
			tfCopy.Call(args)
			return of.Call(args)
		})
		tv.Field(i).Set(newFunc)
	}
}
예제 #8
0
파일: one.go 프로젝트: thriftrw/thriftrw-go
// One wraps the given function to require one less argument, passing in the
// given value instead. The value MUST NOT be nil.
//
// BUG(abg): Variadic functions are not supported.
func One(f interface{}, a interface{}) interface{} {
	if f == nil {
		panic("f is required")
	}
	if a == nil {
		panic("a is required and cannot be nil")
	}

	fType := reflect.TypeOf(f)
	if fType.Kind() != reflect.Func {
		panic(fmt.Sprintf("%v (%v) is not a function", f, fType))
	}

	if fType.IsVariadic() {
		panic(fmt.Sprintf("%v (%v) is variadic", f, fType))
	}

	in := args(fType)
	out := returns(fType)
	if len(in) == 0 {
		panic(fmt.Sprintf("%v (%v) does not accept enough arguments to curry in %v", f, fType, a))
	}

	fVal := reflect.ValueOf(f)
	aVal := reflect.ValueOf(a)
	newFType := reflect.FuncOf(in[1:], out, false)
	return reflect.MakeFunc(newFType, func(args []reflect.Value) []reflect.Value {
		newArgs := make([]reflect.Value, 0, fType.NumIn())
		newArgs = append(newArgs, aVal)
		newArgs = append(newArgs, args...)
		return fVal.Call(newArgs)
	}).Interface()
}
예제 #9
0
// Open retrieves the symbols defined in plugin, from the shared library at path.
// path should omit the file extension (e.g. "plugin" instead of "plugin.so").
// plugin should be a pointer to a struct embedding the Plugin struct.
func Open(plugin interface{}, path string) error {
	v := reflect.ValueOf(plugin)
	t := v.Type()
	if t.Kind() != reflect.Ptr {
		return errors.New("Open expects a plugin to be a pointer to a struct")
	}
	v = v.Elem()
	t = v.Type()
	if t.Kind() != reflect.Struct {
		return errors.New("Open expects a plugin to be a pointer to a struct")
	}
	lib, err := dl.Open(path, 0)
	if err != nil {
		return err
	}
	for i := 0; i < v.NumField(); i++ {
		tf := t.Field(i)
		if tf.Name != _plugin {
			sym := v.Field(i).Interface()
			if err := lib.Sym(tf.Name, &sym); err != nil && tf.Type.Kind() == reflect.Func {
				fn := reflect.MakeFunc(tf.Type, nopFn)
				v.Field(i).Set(fn)
			} else {
				v.Field(i).Set(reflect.ValueOf(sym))
			}
		} else {
			p := Plugin{lib}
			v.Field(i).Set(reflect.ValueOf(p))
		}
	}
	return nil
}
예제 #10
0
파일: call.go 프로젝트: ttthzy/qlang
func function2Func(in *reflect.Value, t reflect.Type) {

	fn := in.MethodByName("Call")
	wrap := func(args []reflect.Value) (results []reflect.Value) {
		ret := fn.Call(args)[0]
		n := t.NumOut()
		if n == 0 {
			return
		}
		if n == 1 {
			if t.Out(0) != typeIntf {
				ret = ret.Elem()
			}
			return []reflect.Value{ret}
		}
		if ret.Kind() != reflect.Slice || ret.Len() != n {
			panic(fmt.Sprintf("unexpected return value count, we need `%d` values", n))
		}
		results = make([]reflect.Value, n)
		for i := 0; i < n; i++ {
			result := ret.Index(i)
			if t.Out(i) != typeIntf {
				result = result.Elem()
			}
			results[i] = result
		}
		return
	}
	*in = reflect.MakeFunc(t, wrap)
}
예제 #11
0
func getPluginProxy(name string, extInterface interface{}) interface{} {
	extInterfaceType := reflect.TypeOf(extInterface).Elem()
	if !hasImplementation(name, extInterfaceType.Name()) {
		return nil
	}
	pluginProxy := reflect.New(extInterfaceType).Elem()
	// loop over fields defined in extInterfaceType,
	// replacing them in v with implementations
	for i, n := 0, extInterfaceType.NumField(); i < n; i++ {
		field := pluginProxy.Field(i)
		structField := extInterfaceType.Field(i)
		newFunc := func(args []reflect.Value) []reflect.Value {
			runner := plugin.loaded[name]
			if runner == nil {
				return []reflect.Value{reflect.ValueOf(nil)}
			}
			value, err := runner.CallPlugin(name, structField.Name, convertArgs(args))
			if err != nil {
				log.Println("plugins:", err)
			}
			if value != nil {
				return []reflect.Value{reflect.ValueOf(value)}
			}
			return []reflect.Value{}
		}
		field.Set(reflect.MakeFunc(field.Type(), newFunc))
	}
	return pluginProxy.Interface()
}
예제 #12
0
파일: 反射2.go 프로젝트: oywc410/MYPG
func main() {
	// swap is the implementation passed to MakeFunc.
	// It must work in terms of reflect.Values so that it is possible
	// to write code without knowing beforehand what the types
	// will be.
	swap := func(in []reflect.Value) []reflect.Value {
		return []reflect.Value{in[1], in[0]}
	}
	// makeSwap expects fptr to be a pointer to a nil function.
	// It sets that pointer to a new function created with MakeFunc.
	// When the function is invoked, reflect turns the arguments
	// into Values, calls swap, and then turns swap's result slice
	// into the values returned by the new function.
	makeSwap := func(fptr interface{}) {
		// fptr is a pointer to a function.
		// Obtain the function value itself (likely nil) as a reflect.Value
		// so that we can query its type and then set the value.
		fn := reflect.ValueOf(fptr).Elem()
		// Make a function of the right type.
		v := reflect.MakeFunc(fn.Type(), swap)
		// Assign it to the value fn represents.
		fn.Set(v)
	}
	// Make and call a swap function for ints.
	var intSwap func(int, int) (int, int)
	makeSwap(&intSwap)
	fmt.Println(intSwap(0, 1))
	// Make and call a swap function for float64s.
	var floatSwap func(float64, float64) (float64, float64)
	makeSwap(&floatSwap)
	fmt.Println(floatSwap(2.72, 3.14))
}
예제 #13
0
// 连接函数 返回error 结束 下一次传递
func JoinBy(t interface{}, fs ...interface{}) interface{} {

	val := reflect.ValueOf(t)
	if val.Kind() != reflect.Func {
		return nil
	}

	for k, v := range fs {
		c := toCaller(v)
		if c == nil {
			return nil
		}
		fs[k] = c
	}

	typ := val.Type()
	r := reflect.MakeFunc(typ, func(args []reflect.Value) (results []reflect.Value) {
		inj := inject.New()
		for _, v := range args {
			inj.Set(v.Type(), v)
		}
		inj = SliceFunc(inj, fs)
		for i := 0; i != typ.NumOut(); i++ {
			results = append(results, inj.Get(typ.Out(i)))
		}
		return
	})
	return r.Interface()
}
예제 #14
0
파일: client.go 프로젝트: linyd2005/go-1
func (c *Client) MakeRpc(rpcName string, fptr interface{}) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = fmt.Errorf("make rpc error")
		}
	}()

	fn := reflect.ValueOf(fptr).Elem()

	nOut := fn.Type().NumOut()
	if nOut == 0 || fn.Type().Out(nOut-1).Kind() != reflect.Interface {
		err = fmt.Errorf("%s return final output param must be error interface", rpcName)
		return
	}

	_, b := fn.Type().Out(nOut - 1).MethodByName("Error")
	if !b {
		err = fmt.Errorf("%s return final output param must be error interface", rpcName)
		return
	}

	f := func(in []reflect.Value) []reflect.Value {
		return c.call(fn, rpcName, in)
	}

	v := reflect.MakeFunc(fn.Type(), f)
	fn.Set(v)

	return
}
예제 #15
0
파일: aop.go 프로젝트: gogap/aop
func (p *AOP) GetProxy(beanID string) (proxy *Proxy, err error) {
	var bean *Bean

	if bean, err = p.beanFactory.GetBean(beanID); err != nil {
		return
	}

	tmpProxy := NewProxy(beanID)

	beanValue := reflect.ValueOf(bean.instance)
	beanType := reflect.TypeOf(bean.instance)
	for i := 0; i < beanValue.NumMethod(); i++ {
		methodV := beanValue.Method(i)
		methodT := beanType.Method(i)

		mType := methodV.Type()

		var metadata MethodMetadata
		if metadata, err = getMethodMetadata(methodT); err != nil {
			return
		}

		newFunc := p.funcWrapper(bean, metadata.Method.Name, mType)
		funcV := reflect.MakeFunc(mType, newFunc)

		metadata.Method.Func = funcV // rewrite to new proxy func

		tmpProxy.registryFunc(metadata)
	}

	proxy = tmpProxy

	return
}
예제 #16
0
func init() {
	makeFunc := func(base func([]reflect.Value) []reflect.Value, fptr interface{}) {
		fn := reflect.ValueOf(fptr).Elem()
		v := reflect.MakeFunc(fn.Type(), base)
		fn.Set(v)
	}

	// getAll(Repository) (int, string)
	getAll := func(in []reflect.Value) []reflect.Value {
		values := in[0].MethodByName("GetAll").Call([]reflect.Value{})
		// values is []reflect.Value returned by reflect.Call.
		// Since GetAll only returns interface{}, we just want the first object in values
		jsonResponse := string(jsonEncode(values[0].Interface()))
		return genericHandlerReturn(http.StatusFound, jsonResponse)
	}

	makeFunc(getAll, &GetAllUnits)

	/*func AddUnit(rw http.ResponseWriter, u Unit, repo IUnitRepository) (int, string) {
		repo.Add(&u)
		rw.Header().Set("Location", fmt.Sprintf("/unit/%d", u.Id))
		return http.StatusCreated, ""
	}
	// add(http.ResponseWriter, entity, Repository) (int, string)
	add := func(in []reflect.Value) []reflect.Value {
		in[2].MethodByName("Add").Call([]reflect.Value{in[1]})
		header := in[0].MethodByName("Header").Call(nil)
		location := reflect.ValueOf("Location")
		locationValue := reflect.ValueOf(fmt.Sprintf("/unit/%d", in[1].FieldByName("Id")))
		reflect.ValueOf(header).MethodByName("Set").Call([]reflect.Value{location, locationValue})
		return genericHandlerReturn(http.StatusCreated, "")
	}

	makeFunc(add, &AddUnit)
	*/

	// get(martini.Params, Repository) (int, string)
	get := func(in []reflect.Value) []reflect.Value {
		params := in[0].Interface().(martini.Params)
		id, err := strconv.Atoi(params["id"])

		if err != nil {
			return notFoundGeneric()
		}

		inGet := []reflect.Value{reflect.ValueOf(id)}
		values := in[1].MethodByName("Get").Call(inGet)

		if values[0].IsNil() {
			return notFoundGeneric()
		}

		jsonResponse := string(jsonEncode(values[0].Interface()))
		return []reflect.Value{reflect.ValueOf(http.StatusOK), reflect.ValueOf(jsonResponse)}
	}

	makeFunc(get, &GetUnit)

}
예제 #17
0
func makeSwap(fptr interface{}) {
	swap := func(in []reflect.Value) []reflect.Value {
		return []reflect.Value{in[1], in[0]}
	}
	fn := reflect.ValueOf(fptr).Elem()
	v := reflect.MakeFunc(fn.Type(), swap)
	fn.Set(v)
}
예제 #18
0
파일: arc.go 프로젝트: reusee/go-packages
func (self *ARC) Clone(p interface{}, nilfunc interface{}) {
	atomic.AddInt32(&self.count, 1)
	funcType := reflect.TypeOf(nilfunc)
	funcImpl := func(args []reflect.Value) []reflect.Value {
		c := atomic.AddInt32(&self.count, -1)
		self.cb(c)
		return nil
	}
	runtime.SetFinalizer(p, reflect.MakeFunc(funcType, funcImpl).Interface())
}
예제 #19
0
// asSingleton wraps funcValue (which must of type.Kind Func, and take no parameters) in a function which only
// calls funcValue once, and caches the returned value for future calls.
func asSingleton(funcValue reflect.Value) reflect.Value {
	var once sync.Once
	var cache []reflect.Value
	return reflect.MakeFunc(funcValue.Type(), func(args []reflect.Value) []reflect.Value {
		once.Do(func() {
			cache = funcValue.Call([]reflect.Value{})
		})
		return cache
	})
}
예제 #20
0
func main() {
	var hello func() // 함수를 담을 변수 선언

	fn := reflect.ValueOf(&hello).Elem() // hello의 주소를 넘긴 뒤 Elem으로 값 정보를 가져옴

	v := reflect.MakeFunc(fn.Type(), h) // h의 함수 정보를 생성

	fn.Set(v) // hello의 값 정보인 fn에 h의 함수 정보 v를 설정하여 함수를 연결

	hello()
}
예제 #21
0
파일: memo.go 프로젝트: yanweijin/tt
func Bind(dst interface{}, ver int, src interface{}) {
	dstFn := reflect.ValueOf(dst).Elem()
	srcFn := reflect.ValueOf(src)
	if dstFn.Type() != srcFn.Type() {
		panic("src and dst function types not identical")
	}
	proxy := reflect.MakeFunc(dstFn.Type(), func(in []reflect.Value) []reflect.Value {
		return lookupOrCall(srcFn, in)
	})
	dstFn.Set(proxy)
}
//take the value of emptyBodyFunction and sets swap function as function body implementation
func (cacheSpot CacheSpot) setSwapAsFunctionBody() {

	//recover the value for function in the pointer
	fn := reflect.ValueOf(cacheSpot.CachedFunc).Elem()

	//put a recently created swap function as a function body for the emptyBodyFunction
	fn.Set(reflect.MakeFunc(fn.Type(), cacheSpot.swapFunction))

	//	Creating cache spot for Swap aop.FindOneType to calling aop.FindOneCustomer
	log.Debug("Creating cache spot: %v->(cache return)->%v ", cacheSpot.cachedFuncName, cacheSpot.hotFunctName)

}
예제 #23
0
// makeSwap expects fptr to be a pointer to a nil function.
// It sets that pointer to a new function created with MakeFunc.
// When the function is invoked, reflect turns the arguments
// into Values, calls swap, and then turns swap's result slice
// into the values returned by the new function.
func makeSwap(fptr interface{}) {
	// fptr is a pointer to a function.
	// Obtain the function value itself (likely nil) as a reflect.Value
	// so that we can query its type and then set the value.
	fn := reflect.ValueOf(fptr).Elem()

	// Make a function of the right type.
	v := reflect.MakeFunc(fn.Type(), swap)

	// Assign it to the value fn represents.
	fn.Set(v)
}
예제 #24
0
파일: app.go 프로젝트: reusee/app
func (a *Application) FinishLoad() {
	// handle defs / impls
	for name, info := range a.defs {
		fnPtr := info.ptr
		impls := a.impls[name]
		if len(impls) == 0 {
			panic(sp("no implementation for %s", name))
		}
		fnType := reflect.TypeOf(fnPtr).Elem()
		for _, impl := range impls {
			if t := reflect.TypeOf(impl); t != fnType {
				panic(sp("defined %v, implemented %v", fnType, t))
			}
		}
		handler, ok := fnHandlers[fnType]
		if ok {
			handler(fnPtr, impls)
		} else {
			implValues := make([]reflect.Value, 0, len(impls))
			for _, impl := range impls {
				implValues = append(implValues, reflect.ValueOf(impl))
			}
			reflect.ValueOf(fnPtr).Elem().Set(reflect.MakeFunc(fnType,
				func(args []reflect.Value) (ret []reflect.Value) {
					for _, impl := range implValues {
						impl.Call(args)
					}
					return
				}))
		}
		if info.provides {
			a.provides[name] = reflect.ValueOf(fnPtr).Elem().Interface()
		}
	}

	// match provides and requires
	for name, provide := range a.provides {
		requires := a.requires[name]
		provideValue := reflect.ValueOf(provide)
		for _, require := range requires {
			requireValue := reflect.ValueOf(require).Elem()
			if provideValue.Type() != requireValue.Type() {
				panic(sp("%s not match, %v provided, %v required", name, provideValue.Type(), requireValue.Type()))
			}
			requireValue.Set(provideValue)
		}
		delete(a.requires, name)
	}
	for name, _ := range a.requires {
		panic(sp("%s not provided", name))
	}

}
예제 #25
0
파일: fieldinfo.go 프로젝트: opentable/sous
func (fi *FieldInfo) validateKeyField() error {
	if fi.KeyField == "" {
		return nil
	}
	if fi.ElemType == nil {
		return nil
	}
	if err := validateName(fi.KeyField); err != nil {
		return err
	}
	if fi.ElemType.Kind() != reflect.Struct {
		return errors.Errorf("element type %s not supported; must be struct", fi.ElemType)
	}
	if fi.KeyType.Kind() != reflect.String {
		return errors.Errorf("key type %s not supported; must be string", fi.KeyType)
	}
	elemKeyField, ok := fi.ElemType.FieldByName(fi.KeyField)
	if !ok {
		return errors.Errorf("%s has no field %q", fi.ElemType, fi.KeyField)
	}
	if elemKeyField.Type != fi.KeyType {
		return errors.Errorf("%s.%s is %s; want %s (from %s)",
			fi.ElemType, elemKeyField.Name, elemKeyField.Type, fi.KeyType, fi.Type)
	}
	getFuncType := reflect.FuncOf([]reflect.Type{fi.ElemType}, []reflect.Type{fi.KeyType}, false)
	ptrToElem := reflect.PtrTo(fi.ElemType)
	setFuncType := reflect.FuncOf([]reflect.Type{ptrToElem, fi.KeyType}, nil, false)
	fi.GetKeyFunc = reflect.MakeFunc(getFuncType, func(in []reflect.Value) []reflect.Value {
		return []reflect.Value{in[0].FieldByName(fi.KeyField)}
	})
	fi.SetKeyFunc = reflect.MakeFunc(setFuncType, func(in []reflect.Value) []reflect.Value {
		elem := in[0].Elem()
		if !elem.IsValid() {
			return nil
		}
		in[0].Elem().FieldByName(fi.KeyField).Set(in[1])
		return nil
	})
	return nil
}
예제 #26
0
func main() {
	var hello func()

	fn := reflect.ValueOf(&hello).Elem()

	v := reflect.MakeFunc(fn.Type(), h)

	fn.Set(v)

	hello()


}
예제 #27
0
func DaynamicFuncPrac11() {
	var hello func() // 함수 담을 변수 선언

	fn := reflect.ValueOf(&hello).Elem()
	// hello 주소 넘김 뒤 Elem으로 값 정보

	v := reflect.MakeFunc(fn.Type(), h) // h함수 정보 생성

	fn.Set(v)
	// hello 값 정보 fn에 h의 함수 정보 v를 설정하여 함수 연결

	hello()
}
예제 #28
0
파일: quango.go 프로젝트: totherme/quango
func (q *quangoMatcher) Match(userPredicate interface{}) (successfulMatch bool, matchErr error) {

	typeOfPredicate := reflect.TypeOf(userPredicate)

	if typeOfPredicate.Kind() != reflect.Func {
		return false, fmt.Errorf("Expected a function, not a %s", typeOfPredicate)
	}

	cleanedPredicate := userPredicate

	if typeOfPredicate.NumOut() == 0 {
		predicateValue := reflect.ValueOf(userPredicate)

		predicateWrapper := func(args []reflect.Value) (returnVals []reflect.Value) {
			returnVals = []reflect.Value{reflect.ValueOf(true)}

			defer func() {
				err := recover()
				if err != nil {
					returnVals = []reflect.Value{reflect.ValueOf(false)}
				}
			}()

			predicateValue.Call(args)

			return
		}

		inType := []reflect.Type{}
		for i := 0; i < typeOfPredicate.NumIn(); i++ {
			inType = append(inType, typeOfPredicate.In(i))
		}

		predicateType := reflect.FuncOf(inType, []reflect.Type{reflect.TypeOf(true)}, false)
		cleanedPredicate = reflect.MakeFunc(predicateType, predicateWrapper).Interface()
	}

	err := quick.Check(cleanedPredicate, nil)

	q.counterexample = "False"
	if err != nil {
		cerr, ok := err.(*quick.CheckError)
		if !ok {
			return false, err
		}
		q.counterexample = fmt.Sprintf("%s", cerr)
		return false, nil
	}

	return true, nil
}
예제 #29
0
파일: mock.go 프로젝트: Smarp/funcmock
func Mock(targetFnPtr interface{}) (controller *MockController) {

	targetFn := reflect.ValueOf(targetFnPtr).Elem()
	controller = &MockController{
		counter:   make(chan int),
		callStack: make(chan map[int]*call),
	}
	go func() { controller.callStack <- make(map[int]*call) }()
	go func() { controller.counter <- 0 }()

	controller.targetFunc = targetFn
	targetFnType := targetFn.Type()
	numberOfOuts := targetFnType.NumOut()

	controller.originalFunc = reflect.ValueOf(targetFn.Interface())

	for i := 0; i < numberOfOuts; i++ {
		controller.defaultYield = append(controller.defaultYield,
			reflect.Zero(targetFnType.Out(i)))
	}

	mockFn := reflect.MakeFunc(targetFnType,
		func(inValueSlice []reflect.Value) (yield []reflect.Value) {
			callCount := controller.incrementCounter()
			theCall := controller.NthCall(callCount - 1)
			var param []interface{}
			for i := 0; i < targetFnType.NumIn(); i++ {
				param = append(param, inValueSlice[i].Interface())
			}
			theCall.updateParam(param)
			if numberOfOuts == len(theCall.yield) {
				// if user has set the return values the spit them out
				for i := 0; i < numberOfOuts; i++ {
					yield = append(yield,
						sanitizeReturn(
							targetFnType.Out(i),
							theCall.yield[i]))
				}
			} else {
				yield = controller.defaultYield
			}
			return yield
		},
	)

	targetFn.Set(mockFn)

	return controller
}
예제 #30
-1
파일: memoize.go 프로젝트: BenLubar/memoize
// Memoize takes a function and returns a function of the same type. The
// returned function remembers the return value(s) of the function call.
// Any pointer values will be used as an address, so functions that modify
// their arguments or programs that modify returned values will not work.
//
// The returned function is safe to call from multiple goroutines if the
// original function is. Panics are handled, so calling panic from a function
// will call panic with the same value on future invocations with the same
// arguments.
//
// The arguments to the function must be of comparable types. Slices, maps,
// functions, and structs or arrays that contain slices, maps, or functions
// cause a runtime panic if they are arguments to a memoized function.
// See also: https://golang.org/ref/spec#Comparison_operators
//
// As a special case, variadic functions (func(x, y, ...z)) are allowed.
func Memoize(fn interface{}) interface{} {
	v := reflect.ValueOf(fn)
	t := v.Type()

	keyType := reflect.ArrayOf(t.NumIn(), interfaceType)
	cache := reflect.MakeMap(reflect.MapOf(keyType, valueType))
	var mtx sync.Mutex

	return reflect.MakeFunc(t, func(args []reflect.Value) (results []reflect.Value) {
		key := reflect.New(keyType).Elem()
		for i, v := range args {
			if i == len(args)-1 && t.IsVariadic() {
				a := reflect.New(reflect.ArrayOf(v.Len(), v.Type().Elem())).Elem()
				for j, l := 0, v.Len(); j < l; j++ {
					a.Index(j).Set(v.Index(j))
				}
				v = a
			}
			vi := v.Interface()
			key.Index(i).Set(reflect.ValueOf(&vi).Elem())
		}
		mtx.Lock()
		val := cache.MapIndex(key)
		if val.IsValid() {
			mtx.Unlock()
			c := val.Interface().(*call)
			<-c.wait
			if c.panicked.IsValid() {
				panic(c.panicked.Interface())
			}
			return c.results
		}
		w := make(chan struct{})
		c := &call{wait: w}
		cache.SetMapIndex(key, reflect.ValueOf(c))
		mtx.Unlock()

		panicked := true
		defer func() {
			if panicked {
				p := recover()
				c.panicked = reflect.ValueOf(p)
				close(w)
				panic(p)
			}
		}()

		if t.IsVariadic() {
			results = v.CallSlice(args)
		} else {
			results = v.Call(args)
		}
		panicked = false
		c.results = results
		close(w)

		return
	}).Interface()
}