Created
December 2, 2015 19:25
-
-
Save imjasonh/190f7f7c7a76d35a2f54 to your computer and use it in GitHub Desktop.
Mad science: A method to take a func and args and give a channel that can be selected on. Useful (arguably) for timing out execution of a func.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"math/rand" | |
"reflect" | |
"time" | |
) | |
func main() { | |
select { | |
case ret := <-Func(func(s string, i int, b bool) string { | |
randSleep() | |
return fmt.Sprintln("values:", s, i, b) | |
}, "foo", 100, true): | |
fmt.Println("did not time out") | |
fmt.Printf("returned %q", ret) | |
case <-time.After(300 * time.Millisecond): | |
fmt.Println("timed out") | |
} | |
} | |
func Func(fn interface{}, args ...interface{}) <-chan interface{} { | |
fnv := reflect.ValueOf(fn) | |
if fnv.Kind() != reflect.Func { | |
panic("not a func") | |
} | |
fnt := reflect.TypeOf(fn) | |
if fnt.NumIn() != len(args) { | |
msg := fmt.Sprintf("incorrect number of args, got %d want %d", fnt.NumIn(), len(args)) | |
panic(msg) | |
} | |
if fnt.NumOut() > 1 { | |
msg := fmt.Sprintf("incorrect number of return values, got %d want <= 1", fnt.NumOut()) | |
panic(msg) | |
} | |
var vargs []reflect.Value | |
for _, a := range args { | |
vargs = append(vargs, reflect.ValueOf(a)) | |
} | |
ch := make(chan interface{}) | |
go func() { | |
ret := fnv.Call(vargs) | |
if len(ret) != 0 { | |
ch <- ret[0].Interface() | |
} | |
close(ch) | |
}() | |
return ch | |
} | |
// randSleep sleeps a random amount of time between 0-500ms | |
func randSleep() { | |
time.Sleep(time.Duration(rand.Intn(5)*100) * time.Millisecond) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment