Can I pass an *io.ReadCloser to a parameter with the type of *io.Reader - go

I am trying to write a function with a parameter of type *io.Reader
func ReadSomething(r *io.Reader) {
<do something with a reader>
}
but then when I try to pass in a pointer to a reader closer to it
func GetWebPage() {
resp, _ := http.Get(<url>)
ReadSomething(&(resp.Body))
}
I get the following error: cannot use &(resp.Body) (value of type *io.ReadCloser) as *io.Reader value.
This makes no sense to me, a dereferenced pointer to a read closer type should implement the methods of Reader, so why am I not able then to pass it in as an argument to a function that expects a pointer to an io.Reader?

io.ReadCloser is an interface type that is a superset of io.Reader interface type. So whenever an io.Reader is required, you may pass a value of io.ReadCloser.
*io.Reader is not an interface type though, it's a pointer (a pointer to interface), so you can't pass *io.ReadCloser.
Please note that these function signatures are a terrible design. You rarely need a pointer to interface (you'll know when you do, see this for an example). Just use interface types, interfaces may wrap pointers if needed.

It's a common misconception in Go that interfaces are more magical and gluey than they really are. As a starting point, all conversions between distinct types must be explicit, and interfaces are distinct types.
Interfaces only carve out a narrow exception to this rule:
Assignability Rules in the Go Specification (which extends to parameter passing).
A value x is assignable to a variable of type T ("x is assignable to T") if [...]
T is an interface type and x implements T.
Or in other words, simple and plain:
x is assignable to T if x implements T.
That's really the whole entire exception, and it makes no expansive effort to generally mesh interfaces, implementations, and structures thereof. As soon as you indirect your interface value through a pointer, you have stepped out of the enumerated territory.

Related

Using msgp with interfaces and maps in Go

I have a map that uses an interface as the key. The map is defined like this MyMap map[Signature]Packets. The interface is Signature, and there will be two structs A and B that implement this interface. I am also using msgp to serialize these two structs.
My issue is that msgp automatically generates methods that use a pointer as the type of the function receiver, which I think will make the key Signature receive pointers. If that was the case, then the key would be different every single time since pointers are different, even though the underlying values are the same. So, every time, I would be creating a new entry instead of finding the existing one and modifying it.
I wonder:
Is there a way to force msgp to generate methods purely with function receivers of the concrete type? Currently, I can only modify the function receivers of auto-generated methods like MarshalMsg and UnmarshalMsg to the concrete type (A or B instead of *A or *B). By doing that, the key of the map is either of type A or of type B, and the map MyMap works fine. However, I know I should not modify the auto-generated code. So, I wonder whether there is an acceptable way to do that.
If there is no way to do 1., is there any workaround to solve this problem? I really need some polymorphic feature of the map's key with the use of msgp.
UPDATE 1 (Apr. 12):
Thanks for sharing your thoughts and offering solutions. Here are some details about my question.
The background is that the map is used for collecting different network events. The two structs implementing the interface Signature are EventSignatureIPv4 and EventSignatureIPv6
type EventSignatureIPv4 struct {
SourceIPv4 [4]byte
Port uint16
Traffic TrafficType
}
type EventSignatureIPv6 struct {
SourceIPv6 [16]byte
Port uint16
Traffic TrafficType
}
and Signature is holding common methods shared between IPv4 and IPv6 data. So, essentially, I want to collect and group corresponding IPv4/v6 events at the runtime. The key of the map is to identify the same source, and the value of the map is to collect events with different destinations.
The msgp library I am using is this one https://pkg.go.dev/github.com/tinylib/msgp#v1.1.5/msgp
Correct me if I am wrong. For compositions in Go, if one of the methods in the method set has a function receiver of the pointer type, then the instance would only be of the pointer type? So here, as I have
func (z *EventSignatureIPv6) MarshalMsg(b []byte) (o []byte, err error) {
/* Auto-generated code */
}
whenever I use Signature to receive the struct EventSignatureIPv6, the struct would only be of type *EventSignatureIPv6?
You are right, "two pointer values are equal if they point to the same variable.", so if you are looking to compare interfaces that may hold pointers to different types, e.g. *A and *B, you are already in trouble.
With that said, I don't think it's an amazing idea to use interface types as map keys in the first place, because you have to deal with some caveats, the first is that:
The comparison operators == and != must be fully defined for operands of the key type
And now you need to be careful about the types that implement the interface. In theory, nobody stops a client from implementing your interface on a defined type with underlying unhashable type, e.g. type UncomparableSignature []int
So you would probably have to add an unexported method on your interface, so that client code outside that package can't implement it. But still, nothing stops code within the same package from implementing it, so this is, at best, maintenance overhead.
Then if the interface holds pointers to zero-values, it's even dependant on the implementation of the specs:
Pointers to distinct zero-size variables may or may not be equal.
Furthermore, you open yourself up to pesky bugs, like variables of type Signature that holds a nil will overwrite each other's values:
var foo Signature
var bar Signature
myMap[foo] = &Packet{/*pretending to have value 1*/}
myMap[bar] = &Packet{/*pretending to have value 2*/}
fmt.Println(myMap[foo]) // 2
A possible solution is, you could replace the map key with a unique id, and you enforce implementors to provide it by declaring the appropriate method on the interface Signature (this still assumes that the implementors can be coordinated to provide unique ids across all of them):
type Signature interface {
UniqueIdent() uint64 // or string, if you prefer
// ...other methods
}
and then
packet := myMap[someSignature.UniqueIdent()]

How to write idiomatic constructor

I'm confused about the constructors in Go. Most constructors I've seen return a struct, but 'Effective Go' suggests that an interface can be returned in some cases, according to the rule of 'Generality'.
I trust 'Effective Go' to provide good ideas, but this doesn't seem to follow the principle of 'accept interfaces, return structs'. I guess that many types implement an interface and nothing more than that, so in that case it would be common to see constructors which return interfaces.
Another related statement is that interfaces should be defined by the consumer, but 'Generality' means that the interface is defined by the producer.
Can someone clarify?
As it has already been mentioned, returning an interface should be considered something exceptional.
Returning errors of type error which is an interface is one of those exception.
Returning an interface that represents an unexported type is the other exception. But why would you have an exported interface that describes an unexported struct instead of just having an exported struct?
The reason is simple, that allows you a higher degree of control on how that struct is constructed.
Compare this two pieces of code:
type MyType struct {
MyField string
}
func NewMyType(value string) MyType {
return MyType{value}
}
func (t MyType) MyMethod() string {
return t.MyField
}
type MyType interface {
MyMethod() string
}
type myType struct {
MyField string
}
func NewMyType(value string) MyType {
return myType{value}
}
func (t myType) MyMethod() string {
return t.MyField
}
In the first case I would be able to do: myVar := MyType{} while in the second case I won't be able to do so, I am forced to use the provided constructor. The first case also allows to modify the field value after creation which is not allowed in the second case. Making the field unexported will solve the second part but not the first.
This example is obviously trivial, but being able to construct invalid structs may have a horrible impact. By having specific constructors you can ensure that the object is in a valid starting state and you will only need to make sure it always stays in a valid state. If you can't ensure that, you may need to check that it is in a valid state at the start of every method.
For example consider a DB request. It needs a DB connection. If the user is able to create a DB request without a DB connection you will have to check that it is valid in every method. If you enforce him to use a constructor you can check at creation time and done.
It depends a bit on your preference and how you view things. Coming from OOP background my take is: there is no point in the constructor if you cannot enforce it. Adding the constructor means - you must supply these values when instantiating this item. If your struct is public, it will be misused and instantiated bypassing the constructor. So it makes sense that the constructor returns the public interface and the struct is private (lowercase). If the struct is public, there is no point in the constructor, because you cannot enforce it. Writing code is a dialogue between writer and reader, making a struct public and having a constructor would tell the reader - here you have the constructor, but you also have a public struct and that would mean that constructor usage is arbitrary. If that is the case, go with that setup
In most cases constructor functions return concrete types (or pointer to a type).
The situations in which returning interfaces might be a good idea is when calling factory functions or builder functions in which underlying concrete type satisfies that interface.
Consider error interface for example, when you call http.NewRequest underlying concentrate error type can be of net.Error, net.DNSError etc. Now try to think how are you going to create an api like this without an error interface if function returns concrete type? Only solution to it I can think of is to create a massive error type for net package and add fields for extra information, but its most probably much harder to maintain, test that kind of error type and not to mention memory bloat.
Whether you choose to return concrete type or an interface is a design choice, some guidelines exists to give solution to common scenarios.

How to avoid a golang function having different behaviors between calling the embedding and embedded types?

Let's say in a 3rd party library we have an interface and a struct implementing this interface. Let's also assume there is a function that takes ParentInterface as argument, which have different behavior for different types.
type ParentInterface interface {
SomeMethod()
}
type ParentStruct struct {
...
}
func SomeFunction(p ParentInterface) {
switch x := p.Type {
case ParentStruct:
return 1
}
return 0
}
In our code we want to use this interface, but with our augmented behavior, so we embed it in our own struct. The compiler actually allows us to call functions about ParentInterface on my struct directly:
type MyStruct struct {
ParentInterface
}
parentStruct := ParentStruct{...}
myStruct := MyStruct{parentStruct}
parentStruct.SomeMethod() // Compiler OK.
myStruct.SomeMethod() // Compiler OK. Result is same. Great.
SomeFunction(parentStruct) // Compiler OK. Result is 1.
SomeFunction(myStruct.ParentInterface) // Compiler OK. Result is 1.
SomeFunction(myStruct) // Compiler OK. Result is 0. (!)
Isn't the last case a problem? I've encountered this kind of bugs more than once. Because I'm happily use MyStruct as an alias of ParentInterface in my code (which is why I define it in the first place), it's so hard to always remember that we cannot call SomeFunction on MyStruct directly (the compiler says we can!).
So what's the best practice to avoid this kind of mistake? Or it's actually a flaw of the compiler, which is supposed to forbid the use of SomeFunction(myStruct) at all since the result is untrustable anyway?
There is no compiler mistake here and your experienced result is the expected one.
Your SomeFunction() function explicitly states it wants to do different things based on the dynamic type of the passed interface value, and that is exactly what happens.
We introduce interfaces in the first place so we don't have to care about the dynamic type that implements it. The interface gives us guarantees about existing methods, and those are the only things you should rely on, you should only call those methods and not do some type-switch or assertion kung-fu.
Of course this is the ideal world, but you should stick to it as much as possible.
Even if in some cases you can't fit everything into the interface, you can again type assert another interface and not a concrete type out of it if you need additional functionality.
A typical example of this is writing an http.Handler where you get the response writer as an interface: http.ResponseWriter. It's quite minimalistic, but the actual type passed can do a lot more. To access that "more", you may use additional type assertions to obtain that extra interface, such as http.Pusher or http.Flusher.
In Go, there is no inheritance and polymorphism. Go favors composition. When you embed a type into another type (struct), the method set of the embedded type will be part of the embedder type. This means any interfaces the embedded type implemented, the embedder will also implement those. And calling methods of those implemented interfaces will "forward" the call to the embedded type, that is, the receiver of those method calls will be the embedded value. This is unless you "override" those methods by providing your own implementation with the receiver type being the embedder type. But even in this case virtual routing will not happen. Meaning if the embedded type has methods A() and B(), and implementation of A() calls B(), if you provide your own B() on the embedder, calling A() (which is of the embedded type) will not call your B() but that of the embedded type.
This is not something to avoid (you can't avoid it), this is something to know about (something to live with). If you know how this works, you just have to take this into consideration and count with it.
Because I'm happily use MyStruct as an alias of ParentInterface in my code (which is why I define it in the first place)
You shouldn't use embedding to create aliases, that is a misuse of embedding. Embedding a type in your own will not be an alias. Implementations of existing methods that check concrete types will "fail" as you experienced (meaning they will not find a match to their expected concrete type).
Unless you want to "override" some methods or implement certain interfaces this way, you shouldn't use embedding. Just use the original type. Simplest, cleanest. If you need aliases, Go 1.9 introduced the type alias feature whose syntax is:
type NewType = ExistingType
After the above declaration NewType will be identical to ExistingType, they will be completely interchangeable (and thus have identical method sets). But know that this does not add any new "real" feature to the language, anything that is possible with type aliases is doable without them. It is mainly to support easier, gradual code refactoring.

Why use non-struct types in Golang? [duplicate]

I am actually learning golang (from .NET) and there is one thing I don't understand about this language.
Sometimes I find this kind of declaration:
https://github.com/golang/crypto/blob/master/ed25519/ed25519.go
// PublicKey is the type of Ed25519 public keys.
type PublicKey []byte
What does it mean exactly?
Is it a creating a struct which inherit from []byte?
Is it just an alias?
I thought golang forbid inheritance.
It's a type declaration, more specifically a type definition. It creates a new type, having []byte as its underlying type:
A type definition creates a new, distinct type with the same underlying type and operations as the given type, and binds an identifier to it.
New types are created because they can simplify using them multiple times, their identifier (their name) may be expressive in other contexts, and–most importantly–so that you can define (attach) methods to it (you can't attach methods to built-in types, nor to anonymous types or types defined in other packages).
This last part (attaching methods) is important, because even though instead of attaching methods you could just as easily create and use functions that accept the "original" type as parameter, only types with methods can implement interfaces that list ("prescribe") those methods, and as mentioned earlier, you can't attach methods to certain types unless you create a new type derived from them.
As an example, the type []int will never implement the sort.Interface required to be sortable (by the sort package), so a new type sort.IntSlice is created (which is type IntSlice []int) to which the required methods are attached, so you can pass a value of type sort.IntSlice to the sort.Sort() function but not a value of type []int. Since sort.IntSlice has []int as its underlying type, if you have a value of []int, you can simply convert it to sort.IntSlice if you want to sort it, like in this example (try it on the Go Playground):
is := []int{1,3,2}
sort.Sort(sort.IntSlice(is))
fmt.Println(is) // Prints: [1 2 3]
When you create a new type, there is no "inheritance" involved. The new type will have 0 methods. If you want "inheritance-like" functionality, you should check out embedding (in relation with struct types), in which case the embedder type will also "have" the methods of the embedded type.

When should I define methods on values (instead of on pointers) in Go?

Having defined
type MyInt int
I would like to define a method .ShowMe() that just prints the value. I can define this either using *MyInt:
func (this *MyInt) ShowMe() {
fmt.Print(*this, "\n")
}
Or using MyInt:
func (this MyInt) ShowMe() {
fmt.Print(this, "\n")
}
In what cases is it recommended to define methods on values, instead of on pointers?
There are two questions to ask yourself when making this decision:
Do I want to be able to modify the receiver's value?
Will copying the receiver's value be expensive?
If the answer to either of these questions is yes, then define the method on a pointer.
In your example, you don't need to modify the receiver's value and copying the receiver isn't expensive.
For deciding the answer to #2, my rule of thumb is: if the receiver is a struct with more than one field, pass by pointer. Otherwise pass by value.
The Go FAQ (CC-licensed) has an answer:
Should I define methods on values or pointers?
func (s *MyStruct) pointerMethod() { } // method on pointer
func (s MyStruct) valueMethod() { } // method on value
For programmers unaccustomed to pointers, the distinction between
these two examples can be confusing, but the situation is actually
very simple. When defining a method on a type, the receiver (s in the
above example) behaves exactly as if it were an argument to the
method. Whether to define the receiver as a value or as a pointer is
the same question, then, as whether a function argument should be a
value or a pointer. There are several considerations.
First, and most important, does the method need to modify the
receiver? If it does, the receiver must be a pointer. (Slices and
maps are reference types, so their story is a little more subtle, but
for instance to change the length of a slice in a method the receiver
must still be a pointer.) In the examples above, if pointerMethod
modifies the fields of s, the caller will see those changes, but
valueMethod is called with a copy of the caller's argument (that's
the definition of passing a value), so changes it makes will be
invisible to the caller.
By the way, pointer receivers are identical to the situation in Java,
although in Java the pointers are hidden under the covers; it's Go's
value receivers that are unusual.
Second is the consideration of efficiency. If the receiver is large, a
big struct for instance, it will be much cheaper to use a pointer
receiver.
Next is 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. See the section on
method sets
for details.
For types such as basic types, slices, and small structs, a value
receiver is very cheap so unless the semantics of the method requires
a pointer, a value receiver is efficient and clear.

Resources