Hi I have a *db* package, which needs to return a slice of struct(of user,order etc type). *In the user pkg, I want the slice of user*. To achieve this, I have tried 4 ways, As shown below.
Attempt 1: Create a callback func using reflection create the user obj & callBack func using reflection & call the callback func with new doc as parameter. This way looks clean to use in user pkg but using reflection is costly. (*please see the benchmark @ bottom of this mail*) package db func QueryResults_CallBack_ReflectionFunc(callBackFuncI interface{}) error { defer client.Close() funcType := reflect.TypeOf(callBackFuncI) docType := funcType.In(0).Elem() callBackFunc := reflect.ValueOf(callBackFuncI) arg := make([]reflect.Value, 1) doc := reflect.New(docType) for client.HasMore() { if err := client.ReadDocument(doc.Interface()); err != nil { return err } arg[0] = doc callBackFunc.Call(arg) } return nil } and at the user pkg side just pass a call back function like... package user func GetUsers_CallBack_ReflectionFunc() []User { users := make([]User, 0, 5) db.QueryResults_CallBack_ReflectionFunc(func(user *User) { users = append(users, *user) }) return users } Attempt 2: Pass the callback func & user object Pass the callback func & user object from user to db pkg, so that, the db pkg doesn't have to create one using reflection, thus saving cost of using reflection package db func QueryResults_CallBack_ObjNFunc(doc interface{}, callBackFunc func(interface{})) error { defer client.Close() for client.HasMore() { if err := client.ReadDocument(doc); err != nil { return err } callBackFunc(doc) } return nil } and in user package it can be used as - *package user*func GetUsers_CallBack_ObjNFunc() []User { users := make([]User, 0, 5) db.QueryResults_CallBack_ObjNFunc(&User{}, func(userI interface{}) { u := userI.(*User) users = append(users, *u) }) return users } Attempt 3: Pass the db client in a callback func package db func QueryResults_CallBack_DBClient(callBackFunc func(DbClient) error) error { defer client.Close() for client.HasMore() { if err := callBackFunc(client); err != nil { return err } } return nil } and in user pkg, it can be used as - *package user*func GetUsers_CallBack_DBClient() []User { users := make([]User, 0, 5) db.QueryResults_CallBack_DBClient(func(client db.DbClient) error { user := User{} if err := client.ReadDocument(&user); err != nil { return err } users = append(users, user) return nil }) return users } Attempt 4: Expose the db client package db func QueryResults_ExposeClient() DbClient { return client } and in user package, handle the read document logic like... package user func GetUsers_ExposeClient() []User { users := make([]User, 0, 5) client := db.QueryResults_ExposeClient() for client.HasMore() { user := User{} client.ReadDocument(&user) users = append(users, user) } client.Close() // responsibility of caller to close the client return users } Benchmark ~/go/src/testReflection master* 5s ❯ go test ./user -cpuprofile cpu.prof -memprofile mem.prof -bench='BenchmarkGetUser*' -run=^a -benchmem BenchmarkGetUsers_CallBackReflectionFunc-12 4426987 263 ns/op 432 B/op 4 allocs/op BenchmarkGetUsers_CallBack_ObjNFunc-12 6293131 186 ns/op 384 B/op 2 allocs/op BenchmarkGetUsers_CallBackClient-12 7858377 147 ns/op 320 B/op 1 allocs/op BenchmarkGetUsers_ExposeClient-12 10273468 106 ns/op 320 B/op 1 allocs/op PProf svg https://raw.githubusercontent.com/amarjeetanandsingh/go_reflection_test/master/pprof_cpu.svg https://raw.githubusercontent.com/amarjeetanandsingh/go_reflection_test/master/pprof_mem.svg Source Code You can find the code at https://github.com/amarjeetanandsingh/go_reflection_test Based on the performance which approach would you suggest? Or any optimisation you can suggest for CallBack_ReflectionFunc()? Or maybe you can purpose a better way? -- 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/2570eb2e-1b46-4c3a-8792-8064acd7e5db%40googlegroups.com.