Golang calling methods on interface pointer - go

I am using Gorp for database access, Gorp has a standard DbMap type, as well as a Transaction type for when you want to be able to roll back. Both types implement the SqlExecutor interface.
I am therefore programming against the SqlExecutor interface, so I can use transactions if I want without needing to change my code.
I then initialise a Gorp DbMap or Transaction and pass it in as a field property. The problem is that I need a pointer to the Gorp "object", else how will I be able to roll back if I use a Transaction if the Gorp "object" is passed by value instead of reference.
I then get a message such as
r.Gorp.Get undefined (type *gorp.SqlExecutor has no field or method Get)
when I try use my code. How do I call the methods?
A code sample is below.
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
}

Maybe you are overthinking the problem, or you may still be under a "call by reference" influence from another language:
gorp.SqlExecutor is an interface and you will never use a pointer to an interface value. Never ever. (Technically this is untrue, but if you actually need a pointer to an interface, you will have mastered Go enough to understand why "never ever" is a really good advice.)
Never think about "call by reference". There is no such thing in Go. Passing a pointer to a function is not "call by reference". Leave that behind.
I assume you did not try to use transactions and do rollbacks on the non-pointer-to-interface code?
Background: In Go, you pass around a pointer to something because of two reasons:
1) You want to, because your struct is really large and you want to avoid copying, or
2) you need to, because the callee wants to modify the original (this is typical for methods with a pointer receiver).
Now an interface value is really tiny (just two words) so reason 1, to pass a pointer to an interface value, does not apply. Reason 2 does not apply in most cases as passing a pointer to an interface value will allow you to change the interface value itself, but most often you would like to modify the value stored inside the interface value. This value stored inside the interface value often is a pointer value which allows to change the value of a struct by calling methods on an interface value which wraps a pointer to this struct. This sounds complicated but isn't: The novice Go programmer just doesn't use pointers to interfaces (as this won't do any good) and the experienced Go programmer doesn't use pointers to interfaces (as it won't do much good) unless he needs to modify an interface value, typically during reflection.

gorp.SqlExecutor is an interface and you will never use a pointer
to an interface value. Never ever.
If this is your goal, you're going about it incorrectly. An
interface is a wrapper, and a contract that guarantees behavior. If
your interface requires that the methods mutate the implementing
type, then the implementing type should be a pointer. A pointer to
the interface itself will not suddenly make the implementing type
mutable.
Your struct 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
}

Related

What meaning of (*SomeStruct)(nil)?

I'm trying to understand this piece code of an ORM library, but I cannot understand what is meaning of (*User)(nil)? First parenthesis is a pointer to User struct, then what is 2nd parenthesis stand for?
type User struct {
Id int64
Name string
Emails []string
}
for _, model := range []interface{}{(*User)(nil), (*Story)(nil)} {
err := db.CreateTable(model, &orm.CreateTableOptions{
// ....
}
}
In Go, nils can by typed, so that a nil of the type *User is different from a nil of the type *Story. So (*User)(nil) is actually a type conversion that makes a typed nil pointer. Further more, the typed pointer is then implicitly converted to interface{} according to the CreateTable signature. Interfaces always store their type along with the data, and that information can be accessed in runtime using reflect, like it happens in ORM.
Because in Go types are not "first-class citizens", i.e. you can't just pass a type around as a value, they use a typed nil pointer idiom that essentially allows providing the desired model type as an argument to CreateTable without creating an instance of it or messing with reflect in the client code.

how to create a function parameter that won't be copied and cannot be null

In golang, Is it possible to create a function that takes a struct with the following constraints:
the struct must not be copied (its relatively big)
the caller must not be able to pass nil
EDIT:
I tried using pointers but that can be set to null. I can't find any good articles on how to use references and it doesn't seem like I can pass by reference.
You can create tiny struct wrapper which holds private pointer to big struct and defines Get method to allow acquisition of this big struct. Inside Get you check if pointer is nil then it panics.
Something like:
type StructHolder struct {
target *BigStruct
}
func (s StructHolder) Get() *BigStruct {
if s.target == nil {
panic("target is nil")
}
return s.target
}
Why would you do this? I'd think its better to pass a pointer and check its value.

How to pass type to function argument in Go

ERROR: type CustomStruct is not an expression.
type CustomStruct struct {
}
func getTypeName(t interface{}) string {
rt := reflect.TypeOf(t).Elem()
return rt.Name()
}
getTypeName(CustomStruct)
How can I pass struct type to function without type instance?
This will work
getTypeName((*CustomStruct)(nil))
But I wonder if there is more simple version..
You can't. You can only pass a value, and CustomStruct is not a value but a type. Using a type identifier is a compile-time error.
Usually when a "type" is to be passed, you pass a reflect.Type value which describes the type. This is what you "create" inside your getTypeName(), but then the getTypeName() will have little left to do:
func getTypeName(t reflect.Type) string {
return t.Name()
}
// Calling it:
getTypeName(reflect.TypeOf(CustomStruct{}))
(Also don't forget that this returns an empty string for anonymous types such as []int.)
Another way is to pass a "typed" nil pointer value as you did, but again, you can just as well use a typed nil value to create the reflect.Type too, without creating a value of the type in question, like this:
t := reflect.TypeOf((*CustomStruct)(nil)).Elem()
fmt.Println(t.Name()) // Prints CustomStruct
Lets resurrect this!
The generics proposal for Go got approved, and that's coming, eventually. When this question was first asked, this probably made more sense as a question, but for anyone looking to implement a generics pattern now, I think I've got an alright API for it.
For now, you can't interact with abstract types, but you can interact with methods on the abstract type, and reflect allows you to examine function signatures. For a method, the 0th is the receiver.
type Example struct {int}
type Generic struct{reflect.Type}
func (p Example) Type() {}
func Reflect(generic interface{}) Generic {
real := reflect.TypeOf(generic)
if real.Kind() != reflect.Func || real.NumIn() < 1 {
panic("reflect.Type.In(n) panics if not a func and if n out of bounds")
}
return Generic{real.In(0)}
}
func (g Generic) Make() interface{} {
return reflect.Zero(g.Type).Interface()
}
func main() {
tOfp := Reflect(Example.Type)
fmt.Printf("Name of the type: %v\n", tOfp.Name())
fmt.Printf("Real (initial)value: %v\n", tOfp.Make())
}
Some quick notes:
The structure of "Example" doesn't matter, rather only that it has a method with a non-pointer receiver.
The definition of a type called "Generic" as a struct is to accomplish what I believed OP's actual intent to be.
The above definition of "Generic" is a struct instead of an interface so that it can have its own method set. Defining "Generic" as an interface, and using a methodset specific to each operand-type used with it would make tons of sense.
If you weren't aware, actual generics are coming in Go 1.18. My example above has no linter or compile protection, and will panic at runtime if used incorrectly. It does work, and will let you reason over abstract types while you wait for a native implementation.
Happy Coding!
From Go version 1.18 a new feature Generics has been introduced. In most of the case instead of passing types to function, we can use generics. Then we will also get compile time error instead of runtime error and it's more efficient than reflect also.
Example Code
func HttpGet[T](url, body) T {
var resp T
return T
}
resp := HttpGet[ResponseType]("dummy.example", nil)

Stringer method requires value

The Go FAQ answers a question regarding the choice of by-value vs. by-pointer receiver definition in methods. One of the statements in that answer is:
If some of the methods of the type must have pointer receivers, the rest should too, so the method set is consistent regardless of how the type is used.
This implies that if I have for a data type a few methods that mutate the data, thus require by-pointer receiver, I should use by-pointer receiver for all the methods defined for that data type.
On the other hand, the "fmt" package invokes the String() method as defined in the Stringer interface by value. If one defines the String() method with a receiver by-pointer it would not be invoked when the associated data type is given as a parameter to fmt.Println (or other fmt formatting methods). This leaves one no choice but to implement the String() method with a receiver by value.
How can one be consistent with the choice of by-value vs. by-pointer, as the FAQ suggests, while fulfilling fmt requirements for the Stringer interface?
EDIT:
In order to emphasize the essence of the problem I mention, consider a case where one has a data type with a set of methods defined with receiver by-value (including String()). Then one wishes to add an additional method that mutates that data type - so he defines it with receiver by-pointer, and (in order to be consistent, per FAQ answer) he also updates all the other methods of that data type to use by-pointer receiver. This change has zero impact on any code that uses the methods of this data type - BUT for invocations of fmt formatting functions (that now require passing a pointer to a variable instead of its value, as before the change). So consistency requirements are only problematic in the context of fmt. The need to adjust the manner one provides a variable to fmt.Println (or similar function) based on the receiver type breaks the capability to easily refactor one's package.
If you define your methods with pointer receiver, then you should use and pass pointer values and not non-pointer values. Doing so the passed value does indeed implement Stringer, and the fmt package will have no problem "detecting" and calling your String() method.
Example:
type Person struct {
Name string
}
func (p *Person) String() string {
return fmt.Sprintf("Person[%s]", p.Name)
}
func main() {
p := &Person{Name: "Bob"}
fmt.Println(p)
}
Output (try it on the Go Playground):
Person[Bob]
If you would pass a value of type Person to fmt.Println() instead of a pointer of type *Person, yes, indeed the Person.String() would not be called. But if all methods of Person has pointer receiver, that's a strong indication that you should use the type and its values as pointers (unless you don't intend its methods to be used).
Yes, you have to know whether you have to use Person or *Person. Deal with it. If you want to write correct and efficient programs, you have to know a lot more than just whether to use pointer or non-pointer values, I don't know why this is a big deal for you. Look it up if you don't know, and if you're lazy, use a pointer as the method set of (the type of) a pointer value contains methods with both pointer and non-pointer receiver.
Also the author of Person may provide you a NewPerson() factory function which you can rely on to return the value of the correct type (e.g. Person if methods have value receivers, and *Person if the methods have pointer receivers), and so you won't have to know which to use.
Answer to later adding a method with pointer receiver to a type which previously only had methods with value receiver:
Yes, as you described in the question, that might not break existing code, yet continuing to use a non-pointer value may not profit from the later added method with pointer receiver.
We might ask: is this a problem? When the type was used, the new method you just added didn't exist. So the original code made no assumption about its existence. So it shouldn't be a problem.
Second consideration: the type only had methods with value receiver, so one could easily assume that by their use, the value was immutable as methods with value receiver cannot alter the value. Code that used the type may have built on this, assuming it was not changed by its methods, so using it from multiple goroutines may have omitted certain synchronization rightfully.
So I do think that adding a new method with pointer receiver to a type that previously only had methods with value receiver should not be "opaque", the person who adds this new method has the responsibility to either modify uses of this type to "switch" to pointers and make sure the code remains safe and correct, or deal with the fact that non-pointer values will not have this new method.
Tips:
If there's a chance that a type may have mutator methods in the future, you should start creating it with methods with pointer receivers. Doing so you avoid later having to go through the process described above.
Another tip could be to hide the type entirely, and only publish interfaces. Doing so, the users of this type don't have to know whether the interface wraps a pointer or not, it just doesn't matter. They receive an interface value, and they call methods of the interface. It's the responsibility of the package author to take care of proper method receivers, and return the appropriate type that implements the interface. The clients don't see this and they don't depend on this. All they see and use is the interface.
In order to emphasize the essence of the problem I mention, consider a case where one has a data type with a set of methods defined with receiver by-value (including String()). Then one wishes to add an additional method that mutates that data type - so he defines it with receiver by-pointer, and (in order to be consistent, per FAQ answer) he also updates all the other methods of that data type to use by-pointer receiver. This change has zero impact on any code that uses the methods of this data type - BUT for invocations of fmt formatting functions (that now require passing a pointer to a variable instead of its value, as before the change).
This is not true. All interface of it and some of type assertions will be affected as well - that is why fmt is affected. e.g. :
package main
import (
"fmt"
)
type I interface {
String() string
}
func (t t) String() string { return "" }
func (p *p) String() string { return "" }
type t struct{}
type p struct{}
func S(i I) {}
func main() {
fmt.Println("Hello, playground")
T := t{}
P := p{}
_ = P
S(T)
//S(P) //fail
}
To understand this from the root, you should know that a pointer method and a value method is different from the very base. However, for convenience, like the omit of ;, golang compiler looks for cases using pointer methods without a pointer and change it back.
As explained here: https://tour.golang.org/methods/6
So back to the orignal question: consistency of pointer methods. If you read the faq more carefully, you will find it is the very last part of considering to use a value or pointer methods. And you can find counter-example in standard lib examples, in container/heap :
// A PriorityQueue implements heap.Interface and holds Items.
type PriorityQueue []*Item
func (pq PriorityQueue) Len() int { return len(pq) }
func (pq PriorityQueue) Less(i, j int) bool {
// We want Pop to give us the highest, not lowest, priority so we use greater than here.
return pq[i].priority > pq[j].priority
}
func (pq PriorityQueue) Swap(i, j int) {
pq[i], pq[j] = pq[j], pq[i]
pq[i].index = i
pq[j].index = j
}
func (pq *PriorityQueue) Push(x interface{}) {
n := len(*pq)
item := x.(*Item)
item.index = n
*pq = append(*pq, item)
}
func (pq *PriorityQueue) Pop() interface{} {
old := *pq
n := len(old)
item := old[n-1]
item.index = -1 // for safety
*pq = old[0 : n-1]
return item
}
// update modifies the priority and value of an Item in the queue.
func (pq *PriorityQueue) update(item *Item, value string, priority int) {
item.value = value
item.priority = priority
heap.Fix(pq, item.index)
}
So, indeed, as the FAQ say, to determine whether to use a pointer methods, take the following consideration in order:
Does the method need to modify the receiver? If yes, use a pointer. If not, there should be a good reason or it makes confusion.
Efficiency. If the receiver is large, a big struct for instance, it will be much cheaper to use a pointer receiver. However, efficiency is not easy to discuss. If you think it is an issue, profile and/or benchmark it before doint so.
Consistency. If some of the methods of the type must have pointer receivers, the rest should too, so the method set is consistent regardless of how the type is used. This, to me, means that if the type shall be used as a pointer (e.g., frequent modify), it should use the method set to mark so. It does not mean one type can only have solely pointer methods or the other way around.
The previous answers here do not address the underlying issue, although the answer from leaf bebop is solid advice.
Given a value, you can in fact invoke either pointer or value receiver methods on it, the compiler will do that for you. However, that does not apply when invoking via interface implementations.
This boils down to this dicussion about interface implementations.
In that discussion the discussion is about implementing interfaces with nil pointers. But the underlying discussion revolves around the same issue: when implementing an interface you must choose the pointer or the value type, and there will be no attempt by the compiler, nor can there be any attempt in golang code, to figure out exactly what type it is, and adjust the interface call accordingly.
So for example, when calling
fmt.Println(object)
you are implementing the arg of type interface{} with object of type X. The fmt code within has no interest in knowing whether the type of object is a pointer type or not. It will not even be able to tell without using reflection. It will simply call String() on whatever type that is.
So if you supplied a value of type X, and there just so happens to be a (*X) String() string method, that does not matter, that method will not be called, it will only type-assert whether that type X implements Stringer, it has no interest if type *X asserts Stringer. Since there is no (X) String() string method, it will move on. It will not attempt to check what X may happen to be, whether it's a pointer type, and if not, whether the associated pointer type implements Stringer, and call that String() method instead.
So this is not really a pointer vs value methods issue, this is an interface implementation issue when implementing interface{} in calls to fmt methods.

Does assigning value to interface copy anything?

I've been trying to wrap my head around the concept of interfaces in Go. Reading this and this helped a lot.
The only thing that makes me uncomfortable is the syntax. Have a look at the example below:
package main
import "fmt"
type Interface interface {
String() string
}
type Implementation int
func (v Implementation) String() string {
return fmt.Sprintf("Hello %d", v)
}
func main() {
var i Interface
impl := Implementation(42)
i = impl
fmt.Println(i.String())
}
My issue is with i = impl. Based on the fact that an interface instance actually holds a pointer reference to the actual data, it would feel more natural for me to do i = &impl. Usually assignment of non-pointer when not using & will make a full memory copy of the data, but when assigning to interfaces this seem to side-step this and instead simply (behind the scenes) assign the pointer to the interface value. Am I right? That is, the data for the int(42) will not be copied in memory?
The data for int(42) will be copied. Try this code:
func main() {
var i Interface
impl := Implementation(42)
i = impl
fmt.Println(i.String())
impl = Implementation(91)
fmt.Println(i.String())
}
(Playground link)
You'll find that the second i.String() still shows 42. Perhaps one of the trickier aspects of Go is that method receivers can be pointers as well.
func (v *Implementation) String() string {
return fmt.Sprintf("Hello %d", *v)
}
// ...
i = &impl
Is what you want if you want the interface to hold a pointer to the original value of impl. "Under the hood" an interface is a struct that either holds a pointer to some data, or the data itself (and some type metadata that we can ignore for our purposes). The data itself is stored if its size is less than or equal to one machine word -- whether it be a pointer, struct, or other value.
Otherwise it will be a pointer to some data, but here's the tricky part: if the type implementing the interface is a struct the pointer will be to a copy of the struct, not the struct assigned to the interface variable itself. Or at least semantically the user can think of it as such, optimizations may allow the value to not be copied until the two diverge (e.g. until you call String or reassign impl).
In short: assigning to an interface can semantically be thought of as a copy of the data that implements the interface. If this is a pointer to a type, it copies the pointer, if it's a big struct, it copies the big struct. The particulars of interfaces using pointers under the hood are for reasons of garbage collection and making sure the stack expands by predictable amounts. As far as the developer is concerned, they should be thought of as semantic copies of the specific instance of the implementing type assigned.

Resources