Skip to content

Instantly share code, notes, and snippets.

@thiagozs
Created August 25, 2026 14:30
Show Gist options
  • Select an option

  • Save thiagozs/0efd45a5bdd372ab26c8f111b51d2f51 to your computer and use it in GitHub Desktop.

Select an option

Save thiagozs/0efd45a5bdd372ab26c8f111b51d2f51 to your computer and use it in GitHub Desktop.
Golang Expr example
package main
import (
"fmt"
"math"
"github.com/expr-lang/expr"
"github.com/expr-lang/expr/vm"
)
// Variables define quais dados podem ser usados nas fórmulas.
type Variables struct {
Speed float64 `expr:"speed"`
Velocity float64 `expr:"velocity"`
Acceleration float64 `expr:"acceleration"`
Grade float64 `expr:"grade"`
}
// Formula representa uma expressão compilada.
type Formula struct {
expression string
program *vm.Program
}
// NewFormula valida e compila uma fórmula.
func NewFormula(expression string) (*Formula, error) {
program, err := expr.Compile(
expression,
expr.Env(Variables{}),
expr.Function(
"avg",
func(params ...any) (any, error) {
if len(params) == 0 {
return nil, fmt.Errorf(
"avg requer pelo menos um parâmetro",
)
}
var total float64
for _, param := range params {
value, ok := param.(float64)
if !ok {
return nil, fmt.Errorf(
"avg aceita somente float64, recebido %T",
param,
)
}
total += value
}
return total / float64(len(params)), nil
},
new(func(float64, float64) float64),
),
expr.Function(
"clamp",
func(params ...any) (any, error) {
value := params[0].(float64)
minimum := params[1].(float64)
maximum := params[2].(float64)
return math.Max(
minimum,
math.Min(value, maximum),
), nil
},
new(func(float64, float64, float64) float64),
),
// Valida e converte o resultado para float64.
expr.AsFloat64(),
)
if err != nil {
return nil, fmt.Errorf(
"fórmula %q inválida: %w",
expression,
err,
)
}
return &Formula{
expression: expression,
program: program,
}, nil
}
// Expression retorna a fórmula original.
func (f *Formula) Expression() string {
return f.expression
}
// Execute executa a fórmula compilada com os valores informados.
func (f *Formula) Execute(variables Variables) (float64, error) {
if f.program == nil {
return 0, fmt.Errorf("fórmula não foi compilada")
}
result, err := expr.Run(f.program, variables)
if err != nil {
return 0, fmt.Errorf(
"erro executando fórmula %q: %w",
f.expression,
err,
)
}
value, ok := result.(float64)
if !ok {
return 0, fmt.Errorf(
"resultado inválido: esperado float64, recebido %T",
result,
)
}
return value, nil
}
func main() {
formulaText := `clamp(avg(speed, velocity) - acceleration * 2, 0.0, 100.0)`
formula, err := NewFormula(formulaText)
if err != nil {
panic(err)
}
input := Variables{
Speed: 80,
Velocity: 70,
Acceleration: 2.5,
Grade: 4,
}
result, err := formula.Execute(input)
if err != nil {
panic(err)
}
fmt.Printf("Fórmula: %s\n", formula.Expression())
fmt.Printf("Resultado: %.2f\n", result)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment