According to “The Go Programming Language” an interface can be seen as a contract. A value that satisfies, say io.Writer, guarantees that there’s a Write method with a specific signature.
But am I right to assume that there is no guarantee as to what that method does? In the case of io.Writer, the Write method could just as well read from the p argument?
Effectively, yes. A value implements a given interface as long as it has methods with the correct names and signatures. Whether or not those methods actually do the expected thing has to be ensured by humans.
Related
The official documentation recommands to use the same receiver name everywhere. But does it really make sense to comply with that?
I mean, I imagine something like func (first Foo) concat(second Foo) (combinded Foo) to be more expressive, while first does only make sense in that very context of concatenation. If we don't go that route, we're basically forced to resort to some agnostic but useless receiver naming like f, wasting an opportuniy for self-documenting code.
Given that 1. You have a good method name, 2. The receiver type is readily apparent from the method declaration, most of the time a short name like f is quite alright. In the case where you need to differentiate the receiver from a parameter, it suggests that you could use a regular function rather than a method, since apparently the receiver doesn't have an obvious meaning that follows from the method name.
Go Wiki: Receiver Names:
The name of a method's receiver should be a reflection of its identity; often a one or two letter abbreviation of its type suffices (such as "c" or "cl" for "Client"). Don't use generic names such as "me", "this" or "self", identifiers typical of object-oriented languages that gives the method a special meaning. In Go, the receiver of a method is just another parameter and therefore, should be named accordingly. The name need not be as descriptive as that of a method argument, as its role is obvious and serves no documentary purpose. It can be very short as it will appear on almost every line of every method of the type; familiarity admits brevity. Be consistent, too: if you call the receiver "c" in one method, don't call it "cl" in another.
If you have a single method, it probably doesn't matter. If you have a type with many (maybe even dozens of methods), it does help if you use the same receiver name in all. It's much easier to read and understand.
Also if you want / have to copy some code from one method to another (refactoring), if the receiver name is the same, you can just do copy / paste and your done, you don't have to start editing the different names.
Also Dave Cheney: Practical Go: Real world advice for writing maintainable Go programs:
2.4. Use a consistent naming style
Another property of a good name is it should be predictable. The reader should be able to understand the use of a name when they encounter it for the first time. When they encounter a common name, they should be able to assume it has not changed meanings since the last time they saw it.
For example, if your code passes around a database handle, make sure each time the parameter appears, it has the same name. Rather than a combination of d *sql.DB, dbase *sql.DB, DB *sql.DB, and database *sql.DB, instead consolidate on something like;
db *sql.DB
Doing so promotes familiarity; if you see a db, you know it’s a *sql.DB and that it has either been declared locally or provided for you by the caller.
Similar advice applies to method receivers; use the same receiver name every method on that type. This makes it easier for the reader to internalise the use of the receiver across the methods in this type.
Also an interesting reading: Neither self nor this: Receivers in Go
In my project so far, I use many traits to permit mocking/stubbing in unit tests for injected dependencies. However, one detail of what I'm doing so far seems so suspicious that I'm surprised it even compiles. I'm worried that something dangerous is going on that I don't see or understand. It's based on the difference between these two method signatures:
fn confirm<T>(subject: &MyTrait<T>) ...
fn confirm<T>(subject: impl MyTrait<T>) ...
I only just discovered the impl ... syntax in method arguments, and it seems like the only documented way to do this, but my tests pass using the other way already, which I came to by intuition based on how Go solves the same problem (size of method argument at compile time, when argument can be any implementer of an interface, and references can come to the rescue).
What is the difference between these two? And why are they both allowed? Do they both represent legitimate use cases, or is my reference syntax (&MyTrait<T>) strictly a worse idea?
The two are different, and serve different purposes. Both are useful, and depending on circumstances one or the other may be the best choice.
The first case, &MyTrait<T>, is preferably written &dyn MyTrait<T> in modern Rust. It is a so-called trait object. The reference points to any type implementing MyTrait<T>, and method calls are dispatched dynamically at runtime. To make this possible, the reference is actually a fat pointer; apart from a pointer to the object it also stores a pointer to the virtual method table of the type of the object, to allow dynamic dispatch. If the actual type of your object only becomes known at runtime, this is the only version you can use, since you need to use dynamic dispatch in that case. The downside of the approach is that there is a runtime cost, and that it only works for traits that are object-safe.
The second case, impl MyTrait<T>, denotes any type implementing MyTrait<T> again, but in this case the exact type needs to be known at compile time. The prototype
fn confirm<T>(subject: impl MyTrait<T>);
is equivalent to
fn confirm<M, T>(subject: M)
where
M: MyTrait<T>;
For each type M that is used in your code, the compiler creates a separate version of confim in the binary, and method calls are dispatched statically at compile time. This version is preferable if all types are known at compile time, since you don't need to pay the runtime cost of dynamically dispatching to the concrete types.
Another difference between the two prototypes is that the first version accepts subject by reference, while the second version consumes the argument that is passed in. This isn't a conceptual difference, though – while the first version cannot be written to consume the object, the second version can easily be written to accept subject by reference:
fn confirm<T>(subject: &impl MyTrait<T>);
Given that you introduced the traits to facilitate testing, it is likely that you should prefer &impl MyTrait<T>.
It is indeed different. The impl version is equivalent to the following:
fn confirm<T, M: MyTrait<T>>(subject: M) ...
so unlike the first version, subject is moved (passed by value) into confirm, rather than passed by reference. So in the impl version, confirm takes ownership of this value.
In go, there's a "prefix" that you can put on a function. How is this useful? What are the use cases for this?
Example:
type a struct {
Thing string
}
func (something a) b() {
fmt.Println(something.Thing)
}
Programming is communication: you are communicating to the machine what it should do, and communicating to other programmers (including your future self). Many higher-level programming constructs serve the purpose of making code more expressive--that is, more clearly stating the programmer's intent.
Go's function receivers are like the "self" object in more traditional object-oriented languages. It's a way of grouping a set of functions together and saying "these methods exist primarily to operate on objects of this type", rather than just being general utility methods that happen to take an argument of that type. In other words, they exist to describe the behavior of the abstract object whose state is described by the structure.
It means that the function is attached to the struct, in this case, so that you can do a.b() somewhere else.
Perhaps this is a silly question, but is there a way to find all functions (in the standard library or GOPATH) that return a specific type?
For example there are many functions that take io.Writer as an argument. Now I want to know how to create an io.Writer and there are many ways to do so. But how can I find all the ways easily without guessing at packages and looking through all the methods to find those that return an io.Writer (or whatever other type I'm after)?
Edit: I should extend my question to also find types that implement a specific interface. Sticking with the io.Writer example (which admittedly was a bad example for the original question) it would be good to have a way to find any types that implement the Writer interface, since those types would be valid arguments for a function that takes takes an io.Writer and thus answer the original question when the type is an interface.
Maybe not the best way but take a look at the search field at the top of the official golang.org website. If you search for "Writer":
http://golang.org/search?q=Writer
You get many results, grouped by categories like
Types
Package-level declarations
Local declarations and uses
and Textual occurrences
Also note that io.Writer is an interface, and we all know how Go handles interfaces: when implementing an interface, there is no declaration of intent, a type implicitly implements an interface if the methods defined by the interface are declared. This means that you won't be able to find many examples where an io.Writer is created and returned because a type might be named entirely different and still be an io.Writer.
Things get a little easier if you look for a non-interface type for example bytes.Buffer.
Also in the documentation of the declaring package of the type the Index section groups functions and methods of the package by type so you will find functions and methods of the same package that return the type you're looking for right under its entry/link in the Index section.
Also note that you can check the dependencies of packages at godoc.org. For example you can see what packages import the io package which may be a good starting point to look for further examples (this would be exhausting in case of package io because it is so general that at the moment 23410 packages import it).
In my days coding I'm personally rare in need to find functions returning Int16 and error(func can return few values in Go, you know)
For second part of your question there exists wonderful cmd implements written by Dominik Honnef go get honnef.co/go/implements
After discover type that satisfy your conditions you can assume constructor for type (something like func NewTheType() TheType) would be just after TheType declaration in source code and docs. It's a proven Go practice.
Say I have a type correct Java method call, such as
f.g(5)
Java 8 now allows method references, so in most cases one can now write
(f::g)(5)
where f::g turns into a lambda function which is then called.
Question: Is this always possible even in cases where f::g is overloaded, or can overloading interfere with the two step process? This would happen if the overload determination must happen at the level of the method reference, before the argument types are known.
Motivation: I am writing compiler-like code, which is why I need to understand these subtleties. I am aware that parenthesizing method references in calls is not a necessary software engineering practice.
No.
However, I think you are confused about what this feature is. The utterance of f.g in the above is not a method reference; it's not even an expression.
A method reference is an expression that looks like Foo::bar and can be converted to a functional interface type.