Skip to content

Instantly share code, notes, and snippets.

@Integralist
Last active May 6, 2026 05:31
Show Gist options
  • Select an option

  • Save Integralist/bb059e61e1551fa54ac7c7576cbc613d to your computer and use it in GitHub Desktop.

Select an option

Save Integralist/bb059e61e1551fa54ac7c7576cbc613d to your computer and use it in GitHub Desktop.
Go: unexported interface methods "seal" the interface support when embedding types
// This code demonstrates how you can embed a type,
// and have it satisfy an interface (`ProblemDetailer`)
// but only for the embedded type.
// This works because the interface uses an unexported method,
// that is part of the embedded type's package.
// https://go.dev/play/p/7lbikIyPHi1
//
// IMPORTANT: If the `isProblem` inteface method was exported (i.e `IsProblem`),
// then our `Fake` struct would pass the `.(errorsx.ProblemDetailer)` type assertion
// e.g. https://go.dev/play/p/pPD3OgtiyHx
package main
import (
"fmt"
"play.ground/errorsx"
)
// Embeds Problem — should satisfy ProblemDetailer via promoted method.
type OrderProblem struct {
errorsx.Problem
OrderID string
}
// Independently defines isProblem() — should NOT satisfy ProblemDetailer
// because unexported methods are package-scoped.
type Fake struct{}
func (Fake) isProblem() {}
func main() {
// 1. Pointer to Problem
var p any = &errorsx.Problem{}
_, ok := p.(errorsx.ProblemDetailer)
fmt.Printf("*Problem satisfies ProblemDetailer: %v\n", ok)
// 2. Value Problem
var v any = errorsx.Problem{}
_, ok = v.(errorsx.ProblemDetailer)
fmt.Printf(" Problem satisfies ProblemDetailer: %v\n", ok)
// 3. Pointer to embedding type
var op any = &OrderProblem{}
_, ok = op.(errorsx.ProblemDetailer)
fmt.Printf("*OrderProblem satisfies ProblemDetailer: %v\n", ok)
// 4. Value embedding type
var ov any = OrderProblem{}
_, ok = ov.(errorsx.ProblemDetailer)
fmt.Printf(" OrderProblem satisfies ProblemDetailer: %v\n", ok)
// 5. Fake with its own isProblem() — different package identity
var f any = Fake{}
_, ok = f.(errorsx.ProblemDetailer)
fmt.Printf(" Fake satisfies ProblemDetailer: %v\n", ok)
// 6. Pointer to Fake
var fp any = &Fake{}
_, ok = fp.(errorsx.ProblemDetailer)
fmt.Printf("*Fake satisfies ProblemDetailer: %v\n", ok)
}
-- go.mod --
module play.ground
go 1.21
-- errorsx/errorsx.go --
package errorsx
// ProblemDetailer identifies RFC 7807 Problem Details payloads.
// Unexported method seals the interface — only types embedding
// Problem (or defined in this package) can satisfy it.
type ProblemDetailer interface {
isProblem()
}
type Problem struct {
Title string
Detail string
}
// Value receiver: both Problem and *Problem satisfy ProblemDetailer.
func (Problem) isProblem() {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment