I'm stuck and I hoped it wouldn't come to that. I wanted to have interfaces for various databases aka "I wanted to support multiple databases" (not debatable). The idea was have ModelInterface (UserModelInterface, CategoryModelInterface etc) which would wrap the model with getters setters StorageInterface which would CRUD the modelinterfaces and finally services which would implement higher level and more convenient functions and use storage interfaces to store data.
Well up to the point where I started creating services everything went mostly smooth. But I hoped I could keep the services database-agnostic. However I can't. https://github.com/dalu/forum/tree/f39df77f5003f71f08f473970b3df1fbd29a5a43 as you can see in line 19 and 20 https://github.com/dalu/forum/blob/f39df77f5003f71f08f473970b3df1fbd29a5a43/server/service/user.go#L19 when I use a concrete model.User (aka line 20) everything works without error. but when I use var m storage.ModelInterface and then call a member function of the interface (SetName) Go panics because nil pointer dereference === RUN TestNewUserService --- FAIL: TestNewUserService (0.00s) panic: runtime error: invalid memory address or nil pointer dereference [recovered] panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x80 pc=0x5ba9f8] goroutine 5 [running]: testing.tRunner.func1(0xc420068b60) /usr/lib/go/src/testing/testing.go:622 +0x29d panic(0x5f1520, 0x721990) /usr/lib/go/src/runtime/panic.go:489 +0x2cf git.icod.de/dalu/forum/server/service.(*UserService).CreateUser(0xc420055f40, 0x62f170, 0x8, 0x630677, 0xd, 0x62e844, 0x6, 0x7ffdb1d66ba1, 0xc420031f68) /home/darko/go/src/git.icod.de/dalu/forum/server/service/user.go:19 +0x28 git.icod.de/dalu/forum/server/service.TestNewUserService(0xc420068b60) /home/darko/go/src/git.icod.de/dalu/forum/server/service/user_test.go:23 +0x1f9 testing.tRunner(0xc420068b60, 0x63af98) /usr/lib/go/src/testing/testing.go:657 +0x96 created by testing.(*T).Run /usr/lib/go/src/testing/testing.go:697 +0x2ca exit status 2 FAIL git.icod.de/dalu/forum/server/service 0.005s However I don't know what the problem was that I had previously an interface *does have* allocated memory but not in the same way the concrete model that fits the interface does so they're not compatible, which lead me to some headaches. So when an interface has memory allocated, why can't I use it as if it has memory allocated? As it is right now I'll have to dump all the StorageInterface and ModelInterface interfaces because it doesn't make sense to use them since I'm bound to a specific model/db at the topmost level,which is "service". "And this is why we can't have nice things". Removing those would also lower the memory footprint when querying for multiple results (slices, find/readall). It's sad, I really wanted to, but I can't. So lesson learned: - keep models the way they are, conrete for the expected database. A mongodb model is different from a pgsql model is different from a cassandra model - storage/repository can be concrete and it should just do CRUD - interface only at the top level, aka service - there is no 1 fits all in Go routes <> handler <interface> service <concrete> storage/repository <concrete> model effectively MySQLUserService MongoDBUserService CassandraUserService RethinkDBUserService but type UserService interface { //... } Question, is there any sane way to solve it without throwing it all away? Hope dies last. Any trick to make it still work with interfaces on the service level without needing to create a concrete database bound instance of a model/struct? -- 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. For more options, visit https://groups.google.com/d/optout.