2 min read
Interface type sets
With what we’ve learned so far about interfaces, we can now draw some general conclusions about the precise definitions of an interfce’s type set. The spec summarizes nicely. General interfaces … Together with method specifications, these elements enable the precise definition of an interface’s type set as follows: The type set of the empty interface is the set of all non-interface types. The type set of a non-empty interface is the intersection of the type sets of its interface elements.
1 min read
General interfaces
Today we’re venturing into generics territory. General interfaces In their most general form, an interface element may also be an arbitrary type term T, or a term of the form ~T specifying the underlying type T, or a union of terms t1|t<sub<>2|…|tn. We haven’t actually learned about type terms yet–they’re coming in a few weeks. But for now, the TL;DR is that they let us specify a type by its name, rather than by its method(s).
2 min read
Embedded interfaces
Embedded interfaces In a slightly more general form an interface T may use a (possibly qualified) interface type name E as an interface element. This is called embedding interface E in T. The type set of T is the intersection of the type sets defined by T’s explicitly declared methods and the type sets of T’s embedded interfaces. In other words, the type set of T is the set of all types that implement all the explicitly declared methods of T and also all the methods of E.
2 min read
Anonymous interfaces
Today we pick up the second half of an example we started with yesterday: Similarly, consider this interface specification, which appears within a type declaration to define an interface called Locker: type Locker interface { Lock() Unlock() } If S1 and S2 also implement func (p T) Lock() { … } func (p T) Unlock() { … } they implement the Locker interface as well as the File interface. We’ve already discussed that a single type may automatically satisfy multiple interfaces, so there’s not much to add here.
Subscribe to Boldly Go: Daily
Every day I'll send you advice to improve your understanding of Go. Don't miss out! I will respect your inbox, and honor my privacy policy.
Unsure? Browse the archive.
2 min read
Implementing interfaces
Basic interfaces … More than one type may implement an interface. For instance, if two types S1 and S2 have the method set func (p T) Read(p []byte) (n int, err error) func (p T) Write(p []byte) (n int, err error) func (p T) Close() error (where T stands for either S1 or S2) then the File interface is implemented by both S1 and S2, regardless of what other methods S1 and S2 may have or share.
1 min read
Interface method names
Basic interfaces … The name of each explicitly specified method must be unique and not blank. interface { String() string String() string // illegal: String not unique _(x int) // illegal: method must have non-blank name } These rules likely look familiar, from our discussion of struct field names, which must also be unique. But there’s a difference: The blank methods are not permitted! Why is that? Well, in effect, the blank identifier is write-only.
2 min read
Basic interfaces
Basic interfaces In its most basic form an interface specifies a (possibly empty) list of methods. The type set defined by such an interface is the set of types which implement all of those methods, and the corresponding method set consists exactly of the methods specified by the interface. Interfaces whose type sets can be defined entirely by a list of methods are called basic interfaces. // A simple File interface.
1 min read
Interface and methods
Interface types … An interface type is specified by a list of interface elements. An interface element is either a method or a type element, where a type element is a union of one or more type terms. A type term is either a single type or a single underlying type. Prior to Go 1.18, interfaces were made up strictly of methods. The introduction of generics complicated things significantly. As such, we’ll talk first about methods, and get to the concept of type elements in a few days.
2 min read
Duck typing
Interface types An interface type defines a type set. A variable of interface type can store a value of any type that is in the type set of the interface. Such a type is said to implement the interface. The value of an uninitialized variable of interface type is nil. InterfaceType = "interface" "{" { InterfaceElem ";" } "}" . InterfaceElem = MethodElem | TypeElem . MethodElem = MethodName Signature .
2 min read
Variadic functions
Generally speaking, Go doesn’t allow for the use of optional function parameters. But there is one exception, and that’s where variadic functions come into play. Function types The final incoming parameter in a function signature may have a type prefixed with .... A function with such a parameter is called variadic and may be invoked with zero or more arguments for that parameter. Probably the most ubiquitous example of a variadic function would be fmt.
2 min read
Unparenthesized results
Function types … Parameter and result lists are always parenthesized except that if there is exactly one unnamed result it may be written as an unparenthesized type. But more directly: Function parameters must always be wrapped in parenthesis. Function reults must be wrapped in parenthesis if there is more than one result, or if the result is named. Further, though not clear from this wording in the spec, if there are no results, no parenthesis are required, even though if there are no parameters, they are still required.