---
name: config_validate
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: pure
signature: "func ConfigValidate(cfg any) ConfigValidation"
description: "Valida una struct de configuracion usando struct tags. Acumula todos los errores (required, format:email, format:url, min, max, oneof) sin detener en el primero. Retorna ConfigValidation con IsValid=true si no hay errores."
tags: [config, validation, env, infra, reflect]
uses_functions: []
uses_types: [config_validation_go_infra, config_error_go_infra]
returns: [config_validation_go_infra]
returns_optional: false
error_type: ""
imports: [fmt, reflect, regexp, strings]
params:
  - name: cfg
    desc: "struct de configuracion (valor o puntero) con tags required, format, min, max, oneof en sus campos exportados"
output: "ConfigValidation con la lista de errores acumulados y el flag IsValid"
tested: true
tests:
  - "struct valido retorna IsValid true"
  - "campo required vacio acumula error"
  - "format email invalido produce error"
  - "format email valido pasa"
  - "format url invalido produce error"
  - "puntero a struct funciona igual"
  - "todos los errores acumulados aunque falle el primero"
test_file_path: "functions/infra/config_validate_test.go"
file_path: "functions/infra/config_validate.go"
---

## Ejemplo

```go
type ServerConfig struct {
    Host  string `required:"true"`
    Port  int    `required:"true" min:"1" max:"65535"`
    Email string `format:"email"`
}

v := ConfigValidate(ServerConfig{Host: "localhost", Port: 8080})
if !v.IsValid {
    for _, e := range v.Errors {
        log.Printf("[%s] %s: %s", e.Tag, e.Field, e.Message)
    }
}
```

## Notas

Funcion pura — usa solo reflect, sin I/O. Soporta tags: `required:"true"`, `format:"email"`, `format:"url"`, `min:"N"`, `max:"N"`, `oneof:"a b c"`. Solo inspecciona campos exportados. No es recursiva — no baja a structs anidados.
