gon

package module
v0.1.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 21, 2025 License: MIT Imports: 5 Imported by: 0

README

GON

Go Reference Tests Linter codecov

Gon is your dynamic and flexible rule-engine!

Experimental

Gon is still experimental and under development, it's not yet stable for production.

Goals

  • Provide dynamic rule/action script evaluation
  • Provide a flexible and extendable library that allows you to control 100% of the rules
    • Choose which nodes to allow or disallow
    • Implement your own custom nodes
    • Allow custom encoding/decoding formats

Usage

Use Gon for:
  • If, then, else requirements
  • Enforcing your ever-changing business requirements
  • Scriptable and dynamic customer conditions/actions
Don't use Gon for:
  • Recursion
  • Long lived execution. Example: infinite loops
Basic Example
func Example_ageVerification() {
	type Person struct {
		Age int64 `gon:"age"`
	}

	person := &Person{Age: 19}

	scope, err := gon.
		NewScope().
		WithValues(gon.Values{
			"person": gon.Literal(person),
		})
	if err != nil {
		panic(err)
	}

	// Write rules as code, and encode them to text:
	exampleRule := gon.If(
		gon.GreaterOrEqual(
			gon.Reference("person.age"),
			gon.Literal(18),
		),
		gon.Literal("pass"),
		gon.Literal("fail"),
	)

	err = encoding.HumanEncode(os.Stdout, exampleRule, encoding.Compact(), encoding.Unnamed())
	if err != nil {
		panic(err)
	}

	// Or write rules as text, and parse them to code.
	ageRuleStr := `if(gte(person.age, 18), "pass", "fail")`

	rule, err := encoding.Decode([]byte(ageRuleStr), encoding.DefaultExpressionCodex)
	if err != nil {
		panic(err)
	}

	value, err := scope.Compute(rule)
	if err != nil {
		panic(err)
	}
	fmt.Printf("\n\nBefore: %s", value)

	person.Age = 5

	value, err = scope.Compute(rule)
	if err != nil {
		panic(err)
	}

	fmt.Printf("\nAfter: %s", value)
	// Output:
	// if(gte(person.age,18),"pass","fail")
	//
	// Before: pass
	// After: fail
}
Further Examples

Standard Nodes

  • Avg
  • Call
  • Coalesce
  • Equal
  • Exists
  • Greater
  • GreaterOrEqual
  • HasPrefix
  • HasSuffix
  • If
  • IsEmpty
  • Literal
  • Not
  • Or
  • Reference
  • Smaller
  • SmallerOrEqual
  • Sum

Limitations

  • Uses reflect package
  • Some node types like Literal, Bool and Time are still not fully customizable

Roadmap

I want to extend the project in the direction of having further:

  • Better slice definition and referencing
  • Benchmarks
  • More nodes
Contributing

If you want to contribute, feel free to open discussions and issues.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	Avg            = nodes.Avg
	Call           = nodes.Call
	Coalesce       = nodes.Coalesce
	Equal          = nodes.Equal
	Exists         = nodes.Exists
	Greater        = nodes.Greater
	GreaterOrEqual = nodes.GreaterOrEqual
	HasPrefix      = nodes.HasPrefix
	HasSuffix      = nodes.HasSuffix
	If             = nodes.If
	IsEmpty        = nodes.IsEmpty
	Literal        = nodes.Literal
	Not            = nodes.Not
	Or             = nodes.Or
	Reference      = nodes.Reference
	Smaller        = nodes.Smaller
	SmallerOrEqual = nodes.SmallerOrEqual
	Sum            = nodes.Sum
)

Functions

func NewScope

func NewScope() *scope

NewScope initializes a new scope. A Scope can be used to evaluate expressions under specific conditions. It can also define context for evaluation and define data for the expressions. It starts with a background context by default.

Types

type Values added in v0.1.9

type Values map[string]adapters.Value

Values defines how scope definitions are configured. The key must be an alphanumeric+underscore+dash string from length 1 to 50, starting with a letter.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL