Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsIn Go, interface satisfaction depends on the method set of a type, not just on which methods you can call through a particular expression. That is why *T may satisfy an interface that T does not, and why embedding T versus *T can change which interfaces a struct satisfies.
Why does *T satisfy an interface but T doesn’t?
A defined type T has the methods declared with receiver T in its method set. The method set of *T includes methods declared with receiver T and methods declared with receiver *T. Interface implementation is based on those method sets: the required method names and signatures must be present. The Go specification’s method-set and interface rules define this behavior.
As an Amazon Associate I earn from qualifying purchases.
For example, Flusher requires a method with a pointer receiver:
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →type Flusher interface {
Flush()
}
type Buffer struct{}
func (b *Buffer) Flush() {}
var _ Flusher = (*Buffer)(nil) // satisfies Flusher
The assignment assertion uses a nil pointer only to check the type relationship at compile time; it does not call Flush. A value of type Buffer does not satisfy Flusher, because Flush is not in Buffer’s method set:
#1 Best Overall
var _ Flusher = Buffer{} // compile-time error
Go does not require a type to declare that it implements an interface. If its method set has the required methods with matching signatures, it implements that interface implicitly. For a basic interface, its type set consists of the non-interface types that implement its listed methods.
Why can I call a pointer receiver on a value, but still get an interface assignment error?
Go permits a convenient method call on an addressable value: if x is addressable and (*T) has method M, then x.M() can act like (&x).M(). This call shorthand does not add M to the method set of T. The Go MethodSets wiki explains the distinction between method calls and method sets.
That difference matters at an interface boundary. A local variable may be addressable, but passing it as an interface value does not change its static type to a pointer:
Free tools Windows power users keep installed
One-click scans. No signup required.
type Worker struct{}
func (w *Worker) Run() {}
type Runner interface {
Run()
}
func start(r Runner) {}
var w Worker
w.Run() // allowed: shorthand for (&w).Run()
start(w) // compile-time error: Worker lacks Run in its method set
start(&w) // allowed: *Worker has Run in its method set
When diagnosing an assignment or argument error, check the type of the value being passed—not only whether the method call works on the expression where it appears.
What methods does an embedded type promote?
An embedded field promotes methods into the method sets of its enclosing struct, but the result depends on whether the field is T or *T. Check the method sets of both the struct type S and its pointer type *S.
Embedded field in S |
Promoted methods in S |
Promoted methods in *S |
|---|---|---|
T |
Methods with receiver T |
Methods with receiver T or *T |
*T |
Methods with receiver T or *T |
Methods with receiver T or *T |
For a value embedding, a pointer-receiver method promoted from T is available through *S, but not in the method set of S. With a pointer embedding, both receiver kinds are promoted into the method sets of S and *S.
Rank #4
type T struct{}
func (T) ValueMethod() {}
func (*T) PointerMethod() {}
type ByValue struct { T }
type ByPointer struct { *T }
var _ interface{ ValueMethod() } = ByValue{}
var _ interface{ PointerMethod() } = (*ByValue)(nil)
var _ interface{ PointerMethod() } = ByValue{} // compile-time error
var _ interface{ PointerMethod() } = ByPointer{}
Promotion also makes methods available through selectors, but conflicting or ambiguous promoted selectors cannot be used. Consult the specification’s struct embedding rules when an embedded field or another method introduces a name collision.
Recommended Free Tools
Does embedding an interface make my type implement it?
Embedding a type or interface is a composition mechanism, not inheritance. An embedded interface contributes its method requirements to the enclosing interface. A concrete struct satisfies that resulting interface only if its method set has every required method.
Best Value
For example, an interface that embeds Reader and Writer requires both sets of methods. Embedding a field in a struct can promote methods that help meet those requirements, but the struct’s method set still determines whether it satisfies the interface. Effective Go’s bufio.ReadWriter example shows composition through embedded reader and writer implementations.
Interface embedding therefore combines contracts; it does not automatically make an unrelated concrete type implement them. If a struct embeds an interface field, its promoted methods derive from that field’s interface method set, but a nil interface field can still cause a panic if a promoted method is invoked before the field holds a concrete value.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.What changed about interfaces with Go generics?
Since Go 1.18, interfaces can describe type sets as well as method requirements. A basic interface—one described by methods and eligible for use as a value type—continues to serve as the familiar runtime interface contract. General interfaces can also include type terms such as ~int, unions, and embedded constraints. A non-basic interface is a constraint, not a type for an ordinary variable or struct field. These rules are specified in the Go specification’s interface and constraint sections.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →type Stringish interface {
~string
}
func Echo[T Stringish](value T) T {
return value
}
// var x Stringish // invalid: Stringish is a constraint, not a value type
The constraint Stringish admits types whose underlying type is string. It does not mean that a value can be stored in a variable of interface type Stringish. Keep these two questions separate: whether a type implements a basic interface, and whether a type argument satisfies a generic constraint.
Why does comparable need a special qualification?
Since Go 1.20, constraint satisfaction has a special case for comparable. A type argument may satisfy a constraint containing comparable even when it does not strictly implement the comparable interface. The specification includes any as a type that can satisfy comparable in a constraint context under this rule. Consequently, “satisfies a constraint” and “implements an interface” are not interchangeable descriptions in every generic type-checking situation.
Quick Recap
How should I check an interface boundary?
- Identify the exact type at the boundary. Is the caller passing
T,*T, or a composite type such asS? - Compare its method set with the interface. Check receiver types and exact signatures; do not infer satisfaction from a successful method call.
- For embedding, inspect both
Sand*S. Determine whether the embedded field isTor*T, then account for promoted methods and any selector ambiguity. - For generics, classify the interface. If it has type terms or other non-basic constraint features, use it as a constraint rather than as an ordinary value type.
- Use a compile-time assertion when it clarifies intent. For example,
var _ Runner = (*Worker)(nil)records that the pointer type must continue to satisfyRunner. For programmatic inspection of Go types and interfaces, see thego/typespackage documentation.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




