| name | go-interfaces |
| description | Diseño de interfaces y contratos en Go. Usar al definir APIs extensibles, preparar código para testing, o cuando se necesita bajo acoplamiento. |
| allowed-tools | Read, Grep, Glob |
Skill: go-interfaces
Diseño de interfaces, contratos y abstracción en Go.
Cuándo usar este skill
- Al definir contratos entre componentes
- Al diseñar APIs extensibles
- Al preparar código para testing
- Cuando se necesita bajo acoplamiento
Principios de Diseño
1. Interfaces Pequeñas (1-3 métodos)
type Reader interface {
Read(p []byte) (n int, err error)
}
type DoEverything interface {
Read() / Write() / Close() / ...
}
2. Definir Donde se USA (No donde se implementa)
package validator
type TerminologyService interface {
ValidateCode(ctx context.Context, system, code string) (bool, error)
}
type Validator struct {
terminology TerminologyService
}
Interfaces del Proyecto GoFHIR
Validator - Interfaces Principales
type TerminologyService interface {
ValidateCode(ctx context.Context, system, code, valueSetURL string) (bool, error)
}
type ReferenceResolver interface {
Resolve(ctx context.Context, reference string) (interface{}, error)
}
type StructureDefinitionProvider interface {
GetStructureDefinition(ctx context.Context, url string) (*StructureDefinition, error)
}
Validator - Pipeline Pattern
type PhaseValidator interface {
Name() string
Priority() int
Validate(ctx context.Context, resource []byte, result *ValidationResult) error
}
type PhaseRegistry interface {
Register(phase PhaseValidator)
GetPhases() []PhaseValidator
}
type ValidationPipeline interface {
Execute(ctx context.Context, resource []byte) (*ValidationResult, error)
}
Validator - Tree Walking
type NodeVisitor interface {
Visit(path string, value interface{}) error
}
FHIRPath - Interfaces de Evaluación
type FuncRegistry interface {
Get(name string) (FuncImpl, bool)
}
type Resolver interface {
Resolve(ctx context.Context, reference string) (interface{}, error)
}
type TerminologyService interface {
ValidateCode(ctx context.Context, system, code, valueSetURL string) (bool, error)
ExpandValueSet(ctx context.Context, valueSetURL string) ([]Code, error)
}
type ProfileValidator interface {
Validate(ctx context.Context, resource interface{}, profileURL string) (bool, error)
}
FHIRPath - Tipos de Valor
type Value interface {
TypeName() string
Equal(other Value) bool
}
type Comparable interface {
Value
Compare(other Comparable) (int, error)
}
type Numeric interface {
Comparable
AsDecimal() decimal.Decimal
}
FHIRPath - Resource Interface
type Resource interface {
ResourceType() string
GetID() string
}
Implementaciones No-Op (Para Opcionalidad)
type NoopTerminologyService struct{}
func (n *NoopTerminologyService) ValidateCode(
ctx context.Context,
system, code, valueSetURL string,
) (bool, error) {
return true, nil
}
func NewValidator(opts ...Option) *Validator {
v := &Validator{
terminology: &NoopTerminologyService{},
}
for _, opt := range opts {
opt(v)
}
return v
}
v := NewValidator(
WithTerminologyService(myRealTermService),
)
Verificación en Compilación
var _ TerminologyService = (*LocalTerminologyService)(nil)
var _ TerminologyService = (*FHIRTerminologyServer)(nil)
var _ PhaseValidator = (*StructurePhase)(nil)
var _ PhaseValidator = (*ConstraintPhase)(nil)
Patrones de Composición con Interfaces
type CompositeTerminologyService struct {
services []TerminologyService
}
func (c *CompositeTerminologyService) ValidateCode(
ctx context.Context,
system, code, valueSetURL string,
) (bool, error) {
for _, svc := range c.services {
valid, err := svc.ValidateCode(ctx, system, code, valueSetURL)
if err == nil && valid {
return true, nil
}
}
return false, nil
}
Uso con Tipos FHIR (r4, r4b, r5)
import "github.com/robertoaraneda/gofhir/r4"
type PatientService interface {
GetPatient(ctx context.Context, id string) (*r4.Patient, error)
SavePatient(ctx context.Context, patient *r4.Patient) error
}
type FHIRPatientService struct {
client *http.Client
baseURL string
}
func (s *FHIRPatientService) GetPatient(ctx context.Context, id string) (*r4.Patient, error) {
resp, err := s.client.Get(s.baseURL + "/Patient/" + id)
}
Checklist
- [ ] ¿La interface tiene 1-3 métodos?
- [ ] ¿Está definida donde se usa (no donde se implementa)?
- [ ] ¿Incluye context.Context en métodos que pueden bloquear?
- [ ] ¿Es fácil de mockear para testing?
- [ ] ¿Hay implementación no-op para cuando es opcional?
- [ ] ¿Hay verificación de compilación (var _ Interface = (*Type)(nil))?
Referencias del Proyecto
validator/interfaces.go → Interfaces principales del validator
validator/phase.go → PhaseValidator, PhaseRegistry
validator/pipeline.go → ValidationPipeline
validator/treewalker.go → NodeVisitor
fhirpath/eval/evaluator.go → FuncRegistry, Resolver, TerminologyService
fhirpath/types/value.go → Value, Comparable, Numeric
fhirpath/options.go → ReferenceResolver