Wikipedia: Data validation
Business rules change frequently. Encoding them in Tengo scripts instead of compiled Go means rules can be updated and reloaded while the host application keeps running.
fmt := import("fmt")
text := import("text")
rules := [
{
field: "username",
check: func(v) { return is_string(v) && len(v) >= 3 && len(v) <= 20 },
message: "must be 3–20 characters",
},
{
field: "age",
check: func(v) { return is_int(v) && v >= 13 && v <= 120 },
message: "must be an integer between 13 and 120",
},
{
field: "email",
check: func(v) { return is_string(v) && text.contains(v, "@") && len(v) > 5 },
message: "must contain @ and be at least 6 characters",
},
{
field: "score",
check: func(v) { return is_float(v) && v >= 0.0 && v <= 1.0 },
message: "must be a float between 0.0 and 1.0",
},
]
validate := func(record) {
errs := []
for _, rule in rules {
val := record[rule.field]
if is_undefined(val) || !rule.check(val) {
errs = append(errs, {field: rule.field, msg: rule.message})
}
}
return errs
}
good := {username: "alice", age: 30, email: "alice@example.com", score: 0.95}
errs := validate(good)
fmt.printf("valid record errors: %d\n", len(errs))
bad := {username: "x", age: 10, email: "notanemail", score: 1.5}
errs = validate(bad)
fmt.printf("invalid record errors: %d\n", len(errs))
for _, e in errs {
fmt.printf(" %-12s %s\n", e.field+":", e.msg)
}
try it
valid record errors: 0 invalid record errors: 4 username: must be 3–20 characters age: must be an integer between 13 and 120 email: must contain @ and be at least 6 characters score: must be a float between 0.0 and 1.0