Hello! I would like to share my use for generics, as there have been a public callout for feedback:
> Second, we know that many people have said that Go needs generics, but we > don’t necessarily know exactly what that means. Does this draft design > address the problem in a useful way? If there is a problem that makes you > think “I could solve this if Go had generics,” can you solve the problem when > using this tool? My goal is to build a caller-friendly API for an engine, which orchestrates processing of various commands. Each command has got a specific input and output type. The engine, besides other things, wraps command execution with various aspects (transactions, performance logging, security checks, queueing,... and possibly load-balancing to different nodes). Therefore, commands aren't implemented as plain functions, but are implemented as handlers identified by keys. I had been playing with generics, and this the solution, which I came up with (for simplistic, reduced, engine scratch) : https://go2goplay.golang.org/p/1CRFNDCI6Lg type Engine struct { Commands map[string]func(input interface{}) interface{} } func (e *Engine) Invoke(key string, input interface{}) interface{} { fmt.Printf("INVOKING COMMAND: %s\n", key) return e.Commands[key](input) } type Command(type I, O) struct { Key string Handler func(input I) O } func (c Command(I, O)) GenericHandler(input interface{}) interface{} { return c.Handler(input.(I)) } func (c Command(I, O)) Invoke(engine *Engine, input I) O { return engine.Invoke(c.Key, input).(O) } var c1 = Command(int, string){ Key: "C1", Handler: func(n int) string { return fmt.Sprintf("first command output %d", n) }, } var c2 = Command(int32, int64){ Key: "C2", Handler: func(n int32) int64 { return int64(n * 3) }, } type C3Input struct{ a, b int } type C3Output struct{ x, y int } var c3 = Command(C3Input, C3Output){ Key: "C3", Handler: func(i C3Input) C3Output { return C3Output{i.b, i.a} }, } func main() { engine := &Engine{ Commands: map[string]func(input interface{}) interface{}{ c1.Key: c1.GenericHandler, c2.Key: c2.GenericHandler, c3.Key: c3.GenericHandler, }, } var ( // explicit types to demonstrate static type-checking c1Result string = c1.Invoke(engine, 5) c2Result int64 = c2.Invoke(engine, 7) c3Result C3Output = c3.Invoke(engine, C3Input{11, 13}) ) fmt.Printf("Result #1: %#v\n", c1Result) fmt.Printf("Result #2: %#v\n", c2Result) fmt.Printf("Result #3: %#v\n", c3Result) } Above example doesn't thoroughly demonstrate the use of returned variables, and static type checking. But, the goal is, that: - input type is statically type-checked, when calling Invoke, - output type is returned with correct static type, and can be used for auto-completion and static type-checking. Maybe, the engine's API can be designed in a better way. However, I hope this feedback will be useful for designing Go's generics. Thank you for the attention! -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CA%2BNaYLPxF7twitScA-TAXpnhX0-jdP8kt2gbVCS-OYX9BR5stQ%40mail.gmail.com.