Golang docs provide a clear guidance on how to name single-method interface (by appending "-er"). But what is the best practice to name a multi-method interface that has only a single struct implementing it?
In C# the interface would have "I" prefix, in Java, the class will have "Impl" suffix. Are there similar guidelines for Golang?
The point of having an interface here is to be able to mock it for unit-testing of components that depend on it.
Here is a specific example of UserManager interface. It is going to be consumed by a web api controller that will translate HTTP requests into method calls on this interface. This web api controller will use most of the methods of UserManager.
type UserManager interface { // Should it be UserManagerInterface ?
GetUser(id int) User
CreateUser(user User)
DeleteUser(id int)
ResetPassword(id int, newPassword string)
VerifyEmail(id int)
}
type UserManagerImpl struct { // -Impl, or -Struct, or something else?
}
The interface is a contract of implicit behaviors (object methods) you invoke as needed without the rigors of explicit declaration. These methods are then added onto user-defined structs to create an interface that is about behavior, not data.
Effective Go: Interface names: By convention, one-method interfaces are named by the method name plus an -er suffix or similar modification to construct an agent noun: Reader , Writer , Formatter , CloseNotifier etc. There are a number of such names and it's productive to honor them and the function names they capture.
For most cases the naming convention in Go is just to use camel case and start with upper case if it's a public field and lower case if it's not. But in words that are acronyms like API or URL they are written in full upper case eg. func ProxyURL(fixedURL *url.
A class or struct can implement multiple interfaces, but a class can only inherit from a single class. For more information about abstract classes, see Abstract and Sealed Classes and Class Members. Interfaces can contain instance methods, properties, events, indexers, or any combination of those four member types.
Coming from Java/C# to Go requires a paradigm shift.
Because they are implemented implicitly, interfaces are defined where they're consumed, not where they're implemented.
Because they're implemented implicitly, smaller interfaces are preferred over larger interfaces, hence the focus on single-method "Verber" interfaces. If you have a function that needs to read bytes, it can take a io.Reader
, and the function can be supplied any type that has that method (regardless what other methods it has). You probably don't have a function that calls all 5 of the methods listed in your interface (if so, that function is probably doing too much).
If you feel like naming a struct and an interface the same thing and therefore need some kind of prefix/suffix, you're probably thinking about it the wrong way and might need to reconsider your design.
DBAL is one area where there is sometimes a real case for a larger interface (though it should probably still be composed of smaller interfaces). But in this case, "Impl" doesn't tell you anything - Java and C# love to have pointless interfaces, Go does not. If you'll only ever have one implementation, the interface is probably useless.
If you will have multiple implementations, the differences between them should guide your naming. For example, you might have a PostgresUserManager
, a MongoUserManager
, and a MockUserManager
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With