Custom errors in golang and pointer receivers - pointers

Reading about value receivers vs pointer receivers across the web and stackoverflow, I understand the basic rule to be: If you don't plan to modify the receiver, and the receiver is relatively small, there is no need for pointers.
Then, reading about implementing the error interface (eg. https://blog.golang.org/error-handling-and-go), I see that examples of the Error() function all use pointer receiver.
Yet, we are not modifying the receiver, and the struct is very small.
I feel like the code is much nicer without pointers (return &appError{} vs return appError{}).
Is there a reason why the examples are using pointers?

First, the blog post you linked and took your example from, appError is not an error. It's a wrapper that carries an error value and other related info used by the implementation of the examples, they are not exposed, and not appError nor *appError is ever used as an error value.
So the example you quoted has nothing to do with your actual question. But to answer the question in title:
In general, consistency may be the reason. If a type has many methods and some need pointer receiver (e.g. because they modify the value), often it's useful to declare all methods with pointer receiver, so there's no confusion about the method sets of the type and the pointer type.
Answering regarding error implementations: when you use a struct value to implement an error value, it's dangerous to use a non-pointer to implement the error interface. Why is it so?
Because error is an interface. And interface values are comparable. And they are compared by comparing the values they wrap. And you get different comparison result based what values / types are wrapped inside them! Because if you store pointers in them, the error values will be equal if they store the same pointer. And if you store non-pointers (structs) in them, they are equal if the struct values are equal.
To elaborate on this and show an example:
The standard library has an errors package. You can create error values from string values using the errors.New() function. If you look at its implementation (errors/errors.go), it's simple:
// Package errors implements functions to manipulate errors.
package errors
// New returns an error that formats as the given text.
func New(text string) error {
return &errorString{text}
}
// errorString is a trivial implementation of error.
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
The implementation returns a pointer to a very simple struct value. This is so that if you create 2 error values with the same string value, they won't be equal:
e1 := errors.New("hey")
e2 := errors.New("hey")
fmt.Println(e1, e2, e1 == e2)
Output:
hey hey false
This is intentional.
Now if you would return a non-pointer:
func New(text string) error {
return errorString{text}
}
type errorString struct {
s string
}
func (e errorString) Error() string {
return e.s
}
2 error values with the same string would be equal:
e1 = New("hey")
e2 = New("hey")
fmt.Println(e1, e2, e1 == e2)
Output:
hey hey true
Try the examples on the Go Playground.
A shining example why this is important: Look at the error value stored in the variable io.EOF:
var EOF = errors.New("EOF")
It is expected that io.Reader implementations return this specific error value to signal end of input. So you can peacefully compare the error returned by Reader.Read() to io.EOF to tell if end of input is reached. You can be sure that if they occasionally return custom errors, they will never be equal to io.EOF, this is what errors.New() guarantees (because it returns a pointer to an unexported struct value).

Errors in go only satisfy the error interface, i.e. provide a .Error() method. Creating custom errors, or digging through Go source code, you will find errors to be much more behind the scenes. If a struct is being populated in your application, to avoid making copies in memory it is more efficient to pass it as a pointer. Furthermore, as illustrated in The Go Programming Language book:
The fmt.Errorf function formats an error message using fmt.Sprintf and returns a new error value. We use it to build descriptive errors by successively prefixing additional context information to the original error message. When the error is ultimately handled by the program’s main function, it should provide a clear causal chain from the root problem to the overall failure, reminiscent of a NASA accident investigation:
genesis: crashed: no parachute: G-switch failed: bad relay orientation
Because error messages are frequently chained together, message strings should not be capitalized and newlines should be avoided. The resulting errors may be long, but they will be self-contained when found by tools like grep.
From this we can see that if a single 'error type' holds a wealth of information, and on top of this we are 'chaining' them together to create a detailed message, using pointers will be the best way to achieve this.

We can look at this from the error handling's perspective, instead of the error creation.
Error Definiton Side's Story
type ErrType1 struct {}
func (e *ErrType1) Error() string {
return "ErrType1"
}
type ErrType2 struct {}
func (e ErrType2) Error() string {
return "ErrType1"
}
Error Handler Side's Story
err := someFunc()
switch err.(type) {
case *ErrType1
...
case ErrType2, *ErrType2
...
default
...
}
As you can see, if you implements a error type on a value receiver, then when you are doing the type assertion, you need to worry about both cases.
For ErrType2, both &ErrType2{} and ErrType2{} satisfy the interface.
Because someFunc returns an error interface, you never know if it returns a struct value or a struct pointer, especially when someFunc isn't written by you.
Therefore, by using a pointer receiver doesn't stop a user from returning a pointer as an error.
That been said, all other aspects such as
Stack vs. Heap (memory allocation, GC pressure) still apply.
Choose your implementation according to your use cases.
In general, I prefer to a pointer receiver for the reason I demonstrated above. I prefer to Friendly API over performance and sometimes, when error type contains huge information, it's more performant.

No :)
https://blog.golang.org/error-handling-and-go#TOC_2.
Go interfaces allow for anything that complies with the error interface to be handled by code expecting error
type error interface {
Error() string
}
Like you mentioned, If you don't plan to modify state there is little incentive to pass around pointers:
allocating to heap
GC pressure
Mutable state and concurrency, etc
On a random rant , Anecdotally, I personally think that seeing examples like this one are why new go programers favor pointer receivers by default.

The tour of go explains the general reasons for pointer receivers pretty well:
https://tour.golang.org/methods/8
There are two reasons to use a pointer receiver.
The first is so that the method can modify the value that its receiver points to.
In general, all methods on a given type should have either value or pointer receivers, but not a mixture of both.

Related

Why does go standard library prefer pointer receivers?

Is there a reason why Go standard library prefers pointer receivers, even where value receivers would work?
For example, in go 1.14 io.multiwriter:
type multiWriter struct {
writers []Writer
}
func (t *multiWriter) Write(p []byte) (n int, err error) {
...
}
...
func MultiWriter(writers ...Writer) Writer {
...
return &multiWriter{allWriters}
}
This would work even if instead of &multiWriter{allWriters}, the function returned multiWriter value, and func (t *multiWriter) Write had a value receiver.
Is there a reason why go standard library consistently prefers pointer receivers?
multiWriter's methods could indeed skip the pointer receivers, but since MultiWriter returns an interface and interfaces in Go only contain a type and a pointer to the data, you would need to separately allocate a struct anyway.
One interesting point here is that, as far as I can tell, this is an implementation detail and not part of the spec. One could imagine an alternative Go implementation which uses a different representation of interfaces in memory, potentially allowing small structs to fit directly in interface values without pointers.
Is there a reason why go standard library consistently prefers pointer receivers
No.
Sometimes it's for compatibility reasons (e.g. because the first version would not have worked on value receivers). Sometimes it's for consistency reasons. Sometimes it's author preference. There is not much to see or learn here.

Pointers sent to function

I have following code in main():
msgs, err := ch.Consume(
q.Name, // queue
//..
)
cache := ttlru.New(100, ttlru.WithTTL(5 * time.Minute)) //Cache type
//log.Println(reflect.TypeOf(msgs)) 'chan amqp.Delivery'
go func() {
//here I use `cache` and `msgs` as closures. And it works fine.
}
I decided to create separate function for instead of anonymous.
I declared it as func hitCache(cache *ttlru.Cache, msgs *chan amqp.Delivery) {
I get compile exception:
./go_server.go:61: cannot use cache (type ttlru.Cache) as type *ttlru.Cache in argument to hitCache:
*ttlru.Cache is pointer to interface, not interface
./go_server.go:61: cannot use msgs (type <-chan amqp.Delivery) as type *chan amqp.Delivery in argument to hitCache
Question: How should I pass msg and cache into the new function?
Well, if the receiving variable or a function parameter expects a value
of type *T — that is, "a pointer to T",
and you have a variable of type T, to get a pointer to it,
you have to get the address of that variable.
That's because "a pointer" is a value holding an address.
The address-taking operator in Go is &, so you need something like
hitCache(&cache, &msgs)
But note that some types have so-called "reference semantics".
That is, values of them keep references to some "hidden" data structure.
That means when you copy such values, you're copying references which all reference the same data structure.
In Go, the built-in types maps, slices and channels have reference semantics,
and hence you almost never need to pass around pointers to the values of such types (well, sometimes it can be useful but not now).
Interfaces can be thought of to have reference semantics, too (let's not for now digress into discussing this) because each value of any interface type contains two pointers.
So, in your case it's better to merely not declare the formal parameters of your function as pointers — declare them as "plain" types and be done with it.
All in all, you should definitely complete some basic resource on Go which explains these basic matters in more detail and more extensively.
You're using pointers in the function signature but not passing pointers - which is fine; as noted in the comments, there is no reason to use pointers for interface or channel values. Just change the function signature to:
hitCache(cache ttlru.Cache, msgs chan amqp.Delivery)
And it should work fine.
Pointers to interfaces are nearly never used. You may simplify things and use interfaces of pass by value.

Collection of Unique Functions in Go

I am trying to implement a set of functions in go. The context is an event server; I would like to prevent (or at least warn) adding the same handler more than once for an event.
I have read that maps are idiomatic to use as sets because of the ease of checking for membership:
if _, ok := set[item]; ok {
// don't add item
} else {
// do add item
}
I'm having some trouble with using this paradigm for functions though. Here is my first attempt:
// this is not the actual signature
type EventResponse func(args interface{})
type EventResponseSet map[*EventResponse]struct{}
func (ers EventResponseSet) Add(r EventResponse) {
if _, ok := ers[&r]; ok {
// warn here
return
}
ers[&r] = struct{}{}
}
func (ers EventResponseSet) Remove(r EventResponse) {
// if key is not there, doesn't matter
delete(ers, &r)
}
It is clear why this doesn't work: functions are not reference types in Go, though some people will tell you they are. I have proof, though we shouldn't need it since the language specification says that everything other than maps, slices, and pointers are passed by value.
Attempt 2:
func (ers EventResponseSet) Add(r *EventResponse) {
// ...
}
This has a couple of problems:
Any EventResponse has to be declared like fn := func(args interface{}){} because you can't address functions declared in the usual manner.
You can't pass a closure at all.
Using a wrapper is not an option because any function passed to the wrapper will get a new address from the wrapper - no function will be uniquely identifiable by address, and all this careful planning is for nought.
Is it silly of me to not accept defining functions as variables as a solution? Is there another (good) solution?
To be clear, I accept that there are cases that I can't catch (closures), and that's fine. The use case that I envision is defining a bunch of handlers and being relatively safe that I won't accidentally add one to the same event twice, if that makes sense.
You could use reflect.Value presented by Uvelichitel, or the function address as a string acquired by fmt.Sprint() or the address as uintptr acquired by reflect.Value.Pointer() (more in the answer How to compare 2 functions in Go?), but I recommend against it.
Since the language spec does not allow to compare function values, nor does it allow to take their addresses, you have no guarantee that something that works at a time in your program will work always, including a specific run, and including different (future) Go compilers. I would not use it.
Since the spec is strict about this, this means compilers are allowed to generate code that would for example change the address of a function at runtime (e.g. unload an unused function, then load it again later if needed again). I don't know about such behavior currently, but this doesn't mean that a future Go compiler will not take advantage of such thing.
If you store a function address (in whatever format), that value does not count as keeping the function value anymore. And if no one else would "own" the function value anymore, the generated code (and the Go runtime) would be "free" to modify / relocate the function (and thus changing its address) – without violating the spec and Go's type safety. So you could not be rightfully angry at and blame the compiler, but only yourself.
If you want to check against reusing, you could work with interface values.
Let's say you need functions with signature:
func(p ParamType) RetType
Create an interface:
type EventResponse interface {
Do(p ParamType) RetType
}
For example, you could have an unexported struct type, and a pointer to it could implement your EventResponse interface. Make an exported function to return the single value, so no new values may be created.
E.g.:
type myEvtResp struct{}
func (m *myEvtResp) Do(p ParamType) RetType {
// Your logic comes here
}
var single = &myEvtResp{}
func Get() EventResponse { return single }
Is it really needed to hide the implementation in a package, and only create and "publish" a single instance? Unfortunately yes, because else you could create other value like &myEvtResp{} which may be different pointers still having the same Do() method, but the interface wrapper values might not be equal:
Interface values are comparable. Two interface values are equal if they have identical dynamic types and equal dynamic values or if both have value nil.
[...and...]
Pointer values are comparable. Two pointer values are equal if they point to the same variable or if both have value nil. Pointers to distinct zero-size variables may or may not be equal.
The type *myEvtResp implements EventResponse and so you can register a value of it (the only value, accessible via Get()). You can have a map of type map[EventResponse]bool in which you may store your registered handlers, the interface values as keys, and true as values. Indexing a map with a key that is not in the map yields the zero value of the value type of the map. So if the value type of the map is bool, indexing it with a non-existing key will result in false – telling it's not in the map. Indexing with an already registered EventResponse (an existing key) will result in the stored value – true – telling it's in the map, it's already registered.
You can simply check if one already been registered:
type EventResponseSet map[*EventResponse]bool
func (ers EventResponseSet) Add(r EventResponse) {
if ers[r] {
// warn here
return
}
ers[r] = true
}
Closing: This may seem a little too much hassle just to avoid duplicated use. I agree, and I wouldn't go for it. But if you want to...
Which functions you mean to be equal? Comparability is not defined for functions types in language specification. reflect.Value gives you the desired behaviour more or less
type EventResponseSet map[reflect.Value]struct{}
set := make(EventResponseSet)
if _, ok := set[reflect.ValueOf(item)]; ok {
// don't add item
} else {
// do add item
set[reflect.ValueOf(item)] = struct{}{}
}
this assertion will treat as equal items produced by assignments only
//for example
item1 := fmt.Println
item2 := fmt.Println
item3 := item1
//would have all same reflect.Value
but I don't think this behaviour guaranteed by any documentation.

What do the terms pointer receiver and value receiver mean in Golang?

I've been getting errors from go saying stuff about pointer receivers and I decided to google what the terms mean and I read different sources and documentation talking about pointer receivers. For example: http://golang.org/doc/faq and http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go.
Though, eventhough they talk about these terms they failed to define them precisely. Though, from the context I think the difference between them are defining variables as pointers like *MyStruct vs MyStruct. Although, I am not 100% sure of their difference, I wanted to get a more official or solid understanding of the terms, specially their difference (pointer receiver and value receiver). If possible some simple example code showing their difference in go would be awesome! (and probably necessary to really understand this)
Like for example, something that is confusing me is, what is the difference between the term pointer and pointer receiver? or Value and value receiver? What does the term receiver add to these concepts?
Since you clarified you're confused by the term receiver and not the pointer/value distinction. In Go "receiver" refers to the value a method is defined on, for purposes of interfaces. You can think of the receiver as a special case of the first argument to a function.
func (m MyStruct) DoStuff()
This is what's known as a "value receiver", it is defined on the value MyStruct. This is functionally identical to:
func DoStuff(m MyStruct)
Except:
With a "receiver" you call the function with ".", like in many OO languages:
m := MyStruct{}
m.DoStuff() // as opposed to DoStuff(m)
The set of methods a type is a receiver on defines the interface it implements:
type DoesStuff interface {
DoStuff()
}
func DoSomething(d DoesStuff) {
d.DoStuff()
}
func main() {
m := MyStruct{}
DoSomething(m)
}
So what's a pointer receiver? It looks like this:
func (m *MyStruct) DoOtherStuff()
The difference is exactly the difference between a pointer and a value. Though minor semantic changes occur. Go will auto address and auto-dereference pointers (in most cases) so m := MyStruct{}; m.DoOtherStuff() still works since Go automatically does (&m).DoOtherStuff() for you. (Naturally, you're free to do m := &MyStruct{}; m.DoOtherStuff as well). Further, the interface is defined on the pointer, so:
type DoesOtherStuff interface {
DoOtherStuff()
}
func DoSomethingElse(d DoesOtherStuff) {
d.DoOtherStuff()
}
func main() {
m := MyStruct{}
// DoSomethingElse(m) will fail since because the interface
// DoesOtherStuff is defined on a pointer receiver and this is a value
DoSomethingElse(&m)
}
If you're still confused about when to use a pointer receiver versus a variable receiver, the short answer is: probably a pointer receiver. The long answer has been answered several times, but I'll link here simply because it was easy to find in my history.

When is it a good idea to return a pointer to a struct?

I'm learning Go, and I'm a little confused about when to use pointers. Specifically, when returning a struct from a function, when is it appropriate to return the struct instance itself, and when is it appropriate to return a pointer to the struct?
Example code:
type Car struct {
make string
model string
}
func Whatever() {
var car Car
car := Car{"honda", "civic"}
// ...
return car
}
What are the situations where I would want to return a pointer, and where I would not want to? Is there a good rule of thumb?
There are two things you want to keep in mind, performance and API.
How is a Car used? Is it an object which has state? Is it a large struct? Unfortunately, it is impossible to answer when I have no idea what a Car is. Truthfully, the best way is to see what others do and copy them. Eventually, you get a feeling for this sort of thing. I will now describe three examples from the standard library and explain why I think they used what they did.
hash/crc32: The crc32.NewIEEE() function returns a pointer type (actually, an interface, but the underlying type is a pointer). An instance of a hash function has state. As you write information to a hash, it sums up the data so when you call the Sum() method, it will give you the state of that one instance.
time: The time.Date function returns a Time struct. Why? A time is a time. It has no state. It is like an integer where you can compare them, preform maths on them, etc. The API designer decided that a modification to a time would not change the current one but make a new one. As a user of the library, if I want the time one month from now, I would want a new time object, not to change the current one I have. A time is also only 3 words in length. In other words, it is small and there would be no performance gain in using a pointer.
math/big: big.NewInt() is an interesting one. We can pretty much agree that when you modify a big.Int, you will often want a new one. A big.Int has no internal state, so why is it a pointer? The answer is simply performance. The programmers realized that big ints are … big. Constantly allocating each time you do a mathematical operation may not be practical. So, they decided to use pointers and allow the programmer to decide when to allocate new space.
Have I answered your question? Probably not. It is a design decision and you need to figure it out on a case by case basis. I use the standard library as a guide when I am designing my own libraries. It really all comes down to judgement and how you expect client code to use your types.
Very losely, exceptions are likely to show up in specific circumstances:
Return a value when it is really small (no more than few words).
Return a pointer when the copying overhead would substantially hurt performance (size is a lot of words).
Often, when you want to mimic an object-oriented style, where you have an "object" that stores state and "methods" that can alter the object, then you would have a "constructor" function that returns a pointer to a struct (think of it as the "object reference" as in other OO languages). Mutator methods would have to be methods of the pointer-to-the-struct type instead of the struct type itself, in order to change the fields of the "object", so it's convenient to have a pointer to the struct instead of a struct value itself, so that all "methods" will be in its method set.
For example, to mimic something like this in Java:
class Car {
String make;
String model;
public Car(String myMake) { make = myMake; }
public setMake(String newMake) { make = newMake; }
}
You would often see something like this in Go:
type Car struct {
make string
model string
}
func NewCar(myMake string) *Car {
return &Car{myMake, ""}
}
func (self *Car) setMake(newMake string) {
self.make = newMake
}

Resources