Methods for calling Golang on an interface pointer

I use Gorp to access the database, Gorp has a standard DbMap type, as well as a Transaction type for when you want to go back. Both types implement the SqlExecutor interface.

Therefore, I program against the SqlExecutor interface, so I can use transactions if I want without changing my code.

Then I initialize the Gorp DbMap or Transaction and pass it as a field property. The problem is that I need a pointer to a Gorp object, otherwise how can I roll back if I use Transaction , if the Gorp object is passed by value instead of a reference.

Then I get a message like

 r.Gorp.Get undefined (type *gorp.SqlExecutor has no field or method Get) 

when i try to use my code. How do I call methods?

The following is sample code.

 package repositories import ( "github.com/coopernurse/gorp" ) type Repository struct { Gorp *gorp.SqlExecutor // <<<< Need pointer so I can rollback } func (r *Repository) GetById(i interface{}, key interface{}) interface{} { obj, err := r.Gorp.Get(i, key) if err != nil { panic(err) } return obj } 
+7
go
source share
2 answers

Perhaps you are thinking too much about the problem, or you may still be influenced by “link-by-link” from another language:

  • gorp.SqlExecutor is an interface, and you will never use a pointer to an interface value. Never. (Technically, this is not true, but if you really need a pointer to an interface that you have mastered, enough to understand why "never never" is really good advice.)
  • Never think of a "call by reference." There is no such thing in Go. Passing a pointer to a function is not a "call by reference". Leave it behind.

I assume that you did not try to use transactions and rolled back from the code without a pointer to the interface?

Reference Information. In Go, you pass a pointer to something for two reasons: 1) you want it because your structure is really big and you want to avoid copying, or 2) you need it because calee wants to change the original (this is typical for methods with a pointer receiver ) Now the value of the interface is really tiny (just two words), so argument 1 is not used to pass a pointer to the value of the interface. In most cases, reason 2 does not apply, because passing a pointer to an interface value will allow you to change the value of the interface itself, but most often you want to change the value stored inside the interface value. This value, stored inside an interface value, is often a pointer value that allows you to change the value of a structure by calling methods by the value of an interface that wraps a pointer to that structure. It sounds complicated, but it isn’t: the Go newbie programmer just doesn’t use interface pointers (since this will not be useful), and the experienced Go programmer doesn’t use interface pointers (since he won’t do much well) if he doesn’t need to change the value of the interface, usually during reflection.

+13
source share
  • gorp.SqlExecutor is an interface, and you will never use a pointer to an interface value. Never.

  • If this is your goal, you are doing it wrong. an interface is a shell and contract that guarantees behavior. If your interface requires methods to mutate the implementation of the type, then the implementation type must be a pointer. A pointer to the interface itself will not suddenly create a mutable implementation type.

  • Your structure should be

     type Repository struct { Gorp gorp.SqlExecutor } func (r *Repository) GetById(i interface{}, key interface{}) interface{} { obj, err := r.Gorp.(gorp.SqlExecutor).Get(i, key) if err != nil { panic(err) } return obj } 
+9
source share

All Articles