Interfaces Basics — Specification¶
Source: Go Language Specification — §Interface_types, §Method_sets, §Type_assertions
Table of Contents¶
- Spec Reference
- Formal Grammar (EBNF)
- Interface Type Rules
- Implementation Satisfaction
- Embedded Interfaces
- Interface Values
- Defined vs Undefined Behavior
- Edge Cases from Spec
- Version History
- Spec Compliance Checklist
- Official Examples
- Related Spec Sections
1. Spec Reference¶
Interface Type — Official Text¶
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.
Source: https://go.dev/ref/spec#Interface_types
Method Set — Official Text¶
The type set of an interface type that is the set of types that satisfy all of its constraints (as defined in Type set). A type T implements an interface I if T is in the type set of I.
Source: https://go.dev/ref/spec#Implementing_an_interface
Implementing an Interface — Official Text¶
A type T implements an interface I if - T is not an interface and is an element of the type set of I; or - T is an interface and the type set of T is a subset of the type set of I.
Source: https://go.dev/ref/spec#Implementing_an_interface
2. Formal Grammar (EBNF)¶
Interface Type¶
InterfaceType = "interface" "{" { InterfaceElem ";" } "}" .
InterfaceElem = MethodElem | TypeElem .
MethodElem = MethodName Signature .
MethodName = identifier .
TypeElem = TypeTerm { "|" TypeTerm } .
TypeTerm = Type | UnderlyingType .
UnderlyingType = "~" Type .
Method Element¶
Embedded Interface¶
Embedded interface — interface element-i sifatida.
3. Interface Type Rules¶
Rule 1: Interface declares method set¶
The interface defines what methods a type must have to satisfy it.
Rule 2: Methods must have unique names¶
Rule 3: Embedded interface members merged¶
type A interface { Foo() }
type B interface { Bar() }
type AB interface { A; B } // type set: {Foo, Bar}
Rule 4: Method conflicts (Go 1.14+)¶
type A interface { M() }
type B interface { M() } // same signature
type AB interface { A; B } // OK — single M
Pre-1.14 — duplicate methods compile error. 1.14+ — same signature allowed.
type A interface { M() }
type B interface { M() string } // different signature
type AB interface { A; B } // compile error — incompatible
Rule 5: Empty interface¶
type any = interface{} // alias (Go 1.18+)
var x any = 42
var y any = "hello"
var z any = struct{}{}
Any type satisfies the empty interface.
4. Implementation Satisfaction¶
Rule: Method set inclusion¶
A type T implements interface I if T's method set includes all methods of I.
Rule: Pointer receiver impact¶
If method M is declared with pointer receiver (func (t *T) M()), only *T's method set includes M. T's method set does not.
type I interface { M() }
type T struct{}
func (t *T) M() {}
var _ I = T{} // compile error — T does not implement I
var _ I = &T{} // OK
Implicit satisfaction¶
There is no implements keyword in Go. Satisfaction is determined by method set inclusion at compile time.
Compile-time assertion¶
The blank identifier discards the value. The compiler verifies *MyFile implements Reader.
5. Embedded Interfaces¶
Embedding¶
type Reader interface { Read([]byte) (int, error) }
type Writer interface { Write([]byte) (int, error) }
type ReadWriter interface {
Reader
Writer
}
// type set: {Read, Write}
Method conflict resolution (1.14+)¶
If embedded interfaces have methods with same name and same signature — merged into one.
If signatures differ — compile error.
Type element (Go 1.18+ generics)¶
type Number interface {
int | int64 | float64
}
type AnyNumber interface {
~int | ~int64 | ~float64 // ~T means T or any type with underlying T
}
These define type sets for generic constraints.
6. Interface Values¶
Internal representation¶
An interface value consists of two components:
- Type: dynamic type of the stored value
- Value: the actual data (or pointer to it)
Nil interface¶
Non-nil interface with nil concrete¶
This is a common pitfall. The interface value has type information; only the concrete value is nil.
Equality¶
Two interface values are equal if: - Both are nil, OR - Their dynamic types are identical AND their dynamic values are equal.
7. Defined vs Undefined Behavior¶
Defined operations¶
| Operation | Behavior |
|---|---|
var i I = T{} | i = (T, T{}) — boxing if value type |
i.M() | dynamic dispatch via itab |
v, ok := i.(T) | type assertion — ok indicates success |
i == nil | true only if i is nil interface (both type and value nil) |
i == j | true if both nil or types match and values equal |
| Calling method on nil-concrete in interface | Method runs with nil receiver |
Illegal operations¶
| Operation | Result |
|---|---|
| Method on interface type as receiver | Compile error |
| Comparing non-comparable interface values | Runtime panic |
| Type assertion on nil interface | Compile error if type known; runtime panic with second form |
8. Edge Cases from Spec¶
Edge Case 1: Interface containing non-comparable type¶
type S struct{ items []int }
var i interface{} = S{items: []int{1}}
var j interface{} = S{items: []int{1}}
// fmt.Println(i == j) // RUNTIME PANIC — S is non-comparable
Spec: comparing interface values containing non-comparable types panics.
Edge Case 2: Method on interface¶
Edge Case 3: Interface as receiver elements¶
T automatically gets M() method (promoted).
Edge Case 4: Type assertion safety¶
var i I = T{}
v := i.(T) // panic if i's dynamic type != T
v, ok := i.(T) // ok = false if mismatch (no panic)
Edge Case 5: Generic constraint syntax¶
Type elements form constraint type sets.
Edge Case 6: Underlying type constraint¶
type Celsius float64
type Float interface {
~float64
}
// Celsius satisfies Float because its underlying type is float64
9. Version History¶
| Go Version | Change |
|---|---|
| Go 1.0 | Interface types and implicit satisfaction. |
| Go 1.0 | Method sets formalized. |
| Go 1.14 | Embedded interfaces with same-signature methods allowed. |
| Go 1.18 | Generics: type elements (int | float64), type sets, ~T constraint syntax. |
| Go 1.18 | any is now a predeclared alias for interface{}. |
| Go 1.18 | comparable constraint introduced. |
| Go 1.21 | min, max, clear added. No interface change. |
10. Spec Compliance Checklist¶
- Method names within an interface are unique.
- Embedded interfaces are correctly merged.
- Method signatures match for embedded interface conflicts (1.14+).
- Pointer-receiver methods are recognized only on
*T. - Nil interface vs nil concrete distinction understood.
- Comparable types respected when interface comparison occurs.
- Type assertion uses two-value form for safety.
- Generic constraints use type elements correctly (1.18+).
11. Official Examples¶
Interface with multiple methods¶
type ReadWriter interface {
Reader
Writer
}
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
Stringer interface (from fmt)¶
Implementation example¶
type File struct {
*os.File
}
func (f *File) Close() error {
if f.File == nil { return nil }
return f.File.Close()
}
// File satisfies io.Closer
var _ io.Closer = (*File)(nil)
12. Related Spec Sections¶
| Section | URL | Relevance |
|---|---|---|
| Interface types | https://go.dev/ref/spec#Interface_types | Interface declaration |
| Method sets | https://go.dev/ref/spec#Method_sets | Implementation rules |
| Implementing an interface | https://go.dev/ref/spec#Implementing_an_interface | Satisfaction rules |
| Type assertions | https://go.dev/ref/spec#Type_assertions | i.(T) semantics |
| Type switches | https://go.dev/ref/spec#Type_switches | switch v := i.(type) |
| Comparison operators | https://go.dev/ref/spec#Comparison_operators | Interface == |
| Type sets | https://go.dev/ref/spec#General_interfaces | Generic constraints |
| Type parameters | https://go.dev/ref/spec#Type_parameters | Generic types |
| Predeclared identifiers | https://go.dev/ref/spec#Predeclared_identifiers | any, comparable, error |