Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
A Go value satisfies an interface only when the method set of its type contains the interface’s required methods with matching signatures. A method call that works because Go implicitly takes a value’s address does not change that method set. Embedding can promote methods, but which methods reach an outer type depends on whether it embeds T or *T.
What decides whether a Go type satisfies an interface?
For a basic interface, Go checks the method set of the type at the point where the value is used. The methods must match the interface’s required method names and signatures. A type does not need to declare that it implements an interface: satisfaction is implicit. These rules are defined by the Go specification.
For a defined type T, its method set contains methods declared with receiver T. The method set of *T contains methods declared with receiver T or *T. That difference is why an interface assignment may accept a pointer and reject a value.
type Flusher interface {
Flush() error
}
type Buffer struct{}
func (*Buffer) Flush() error {
return nil
}
var _ Flusher = (*Buffer)(nil) // valid
// var _ Flusher = Buffer{} // invalid: Buffer's method set lacks Flush
The blank-identifier declarations are compile-time checks: the right-hand value must be assignable to the interface on the left. A pointer to Buffer has the required method in its method set; a Buffer value does not.
#1 Best Overall
Why does *T satisfy an interface but T doesn’t?
Because a pointer-receiver method belongs to the method set of *T, not T. If an interface requires that method, a value whose static type is T cannot satisfy the interface just because it is possible to take the value’s address somewhere else.
This matters at API boundaries. A function parameter declared as an interface receives the actual value passed to it. If you pass a T, Go checks T’s method set; it does not silently replace the argument with &value. Pass a *T when the required method is only in the pointer type’s method set.
Why can I call a pointer receiver on a value, but still get an interface assignment error?
Go permits convenient method-call shorthand on an addressable value. If x has type T and M has receiver *T, then x.M() can be treated as (&x).M() when x is addressable. This is a call rule, not a change to T’s method set; the Go Wiki’s MethodSets explanation illustrates the distinction.
type Counter struct{}
func (*Counter) Increment() {}
func update() {
var c Counter
c.Increment() // works: c is addressable, so Go can take its address
// var _ interface{ Increment() } = c // invalid
var _ interface{ Increment() } = &c // valid
}
The assignment checks the static type of the value being assigned. c is a Counter; &c is a *Counter. The fact that c.Increment() is legal does not make the first assignment valid.
What methods does an embedded type promote?
Embedding promotes eligible methods into the method sets of the containing struct and its pointer. The exact result depends on whether the embedded field is T or *T. Check S and *S separately rather than assuming they expose identical method sets. The promotion rules are specified in the Go specification.
If S embeds T
Both S and *S include promoted methods whose receiver is T. The method set of *S also includes promoted methods whose receiver is *T.
type Reader struct{}
func (Reader) Read() {}
func (*Reader) Reset() {}
type S struct {
Reader
}
var _ interface{ Read() } = S{} // valid
var _ interface{ Reset() } = (*S)(nil) // valid
// var _ interface{ Reset() } = S{} // invalid
Here, S promotes Read, but not Reset. The pointer type *S promotes both.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
If S embeds *T
Both S and *S include promoted methods whose receiver is T or *T. With the same Reader methods, this definition promotes both methods to both method sets:
type S2 struct {
*Reader
}
var _ interface{ Read() } = S2{}
var _ interface{ Reset() } = S2{}
Promotion does not override selector ambiguity. If multiple embedded fields promote a method with the same name at the same depth, the selector can be ambiguous, so it cannot be used as an available promoted method.
Rank #4
Embedding is composition, not inheritance
Embedding reuses methods through promotion; it does not create a subtype relationship. Effective Go demonstrates the composition pattern with bufio.ReadWriter: embedding reader and writer implementations promotes their methods, allowing the composite to satisfy the related reader and writer interfaces when its method set contains the required methods.
Does embedding an interface make my type implement it?
Embedding one interface inside another combines requirements: the resulting interface requires the methods contributed by each embedded interface, along with any methods it declares itself. A concrete type satisfies that combined interface only if its own method set meets all of those requirements.
type Reader interface {
Read()
}
type Writer interface {
Write()
}
type ReadWriter interface {
Reader
Writer
}
ReadWriter requires both Read and Write; embedding the interface declarations does not add either method to a concrete type. Go’s struct-embedding rules also distinguish embedded fields from interface composition: an interface type cannot be used as an embedded struct field. A named interface-valued field is a field, not a way to promote its methods into the containing struct’s method set.
Best Value
What changed about interfaces with Go generics?
Since Go 1.18, interfaces can describe type sets for generic constraints as well as the familiar method contracts used for values. A basic interface, such as one listing methods, can be used as a value type. A non-basic interface can include type terms or unions and is used as a constraint, not as the type of an ordinary variable or struct field. The specification’s interface section defines these distinctions.
Basic interfaces and type-set constraints
For a basic interface, the type set consists of non-interface types that implement its listed methods. Interface embedding intersects requirements: a type must meet the requirements contributed by every embedded interface and every explicitly listed method.
Constraint interfaces can add exact type terms, underlying-type terms such as ~int, and unions alongside method requirements. These terms restrict which types may be used as type arguments; they do not turn the constraint into an ordinary runtime value type.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteGo 1.20 and the special case for comparable
Since Go 1.20, satisfying a generic constraint is not interchangeable in every case with implementing an interface. The specification adds a special satisfaction rule for comparable: a type argument can satisfy a constraint containing comparable even when it does not strictly implement the comparable interface. For example, any can satisfy comparable as a constraint under that rule. Treat this as a generic constraint-checking exception, not as a change to ordinary interface assignment.
How to diagnose an interface assignment failure
- Read the required method signatures. Names and signatures must match; a similarly named method with different parameters or results does not satisfy the interface.
- Identify the exact static type at the boundary. Decide whether the expression is
Tor*T. Do not use successful calls on an addressable local as evidence thatTsatisfies the interface. - Account for embedding. If the type is a struct, note whether it embeds
Tor*T, then determine the promoted methods in bothSand*S. Check for ambiguous selectors. - Classify the interface. If it is a basic interface used as a value type, check its required methods against the value’s method set. If it is a non-basic generic constraint, also account for its type terms and any constraint-specific satisfaction rules.
- Add a compile-time assertion near the type. For example,
var _ SomeInterface = (*T)(nil)states that the pointer type is expected to satisfy the interface. UseT{}instead only when the value type itself is meant to satisfy it.
For static analysis tools that need to inspect Go types and method sets programmatically, the standard go/types package provides type-analysis APIs.
Quick Recap
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.

