{"id":37213434,"url":"https://github.com/linuxerwang/govaluate","last_synced_at":"2026-01-15T00:37:36.622Z","repository":{"id":65733071,"uuid":"96503750","full_name":"linuxerwang/govaluate","owner":"linuxerwang","description":"Arbitrary expression evaluation for golang","archived":false,"fork":true,"pushed_at":"2017-07-03T21:53:55.000Z","size":278,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-06-20T00:38:11.670Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"Knetic/govaluate","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/linuxerwang.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-07-07T05:53:07.000Z","updated_at":"2024-06-20T00:38:11.671Z","dependencies_parsed_at":"2023-02-07T05:41:46.713Z","dependency_job_id":null,"html_url":"https://github.com/linuxerwang/govaluate","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/linuxerwang/govaluate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linuxerwang%2Fgovaluate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linuxerwang%2Fgovaluate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linuxerwang%2Fgovaluate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linuxerwang%2Fgovaluate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/linuxerwang","download_url":"https://codeload.github.com/linuxerwang/govaluate/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linuxerwang%2Fgovaluate/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28439834,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-15T00:34:46.850Z","status":"ssl_error","status_checked_at":"2026-01-15T00:34:46.551Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-15T00:37:35.692Z","updated_at":"2026-01-15T00:37:36.608Z","avatar_url":"https://github.com/linuxerwang.png","language":"Go","readme":"govaluate\n====\n\n[![Build Status](https://travis-ci.org/Knetic/govaluate.svg?branch=master)](https://travis-ci.org/Knetic/govaluate)\n[![Godoc](https://godoc.org/github.com/Knetic/govaluate?status.png)](https://godoc.org/github.com/Knetic/govaluate)\n\n\nProvides support for evaluating arbitrary C-like artithmetic/string expressions.\n\nWhy can't you just write these expressions in code?\n--\n\nSometimes, you can't know ahead-of-time what an expression will look like, or you want those expressions to be configurable.\nPerhaps you've got a set of data running through your application, and you want to allow your users to specify some validations to run on it before committing it to a database. Or maybe you've written a monitoring framework which is capable of gathering a bunch of metrics, then evaluating a few expressions to see if any metrics should be alerted upon, but the conditions for alerting are different for each monitor.\n\nA lot of people wind up writing their own half-baked style of evaluation language that fits their needs, but isn't complete. Or they wind up baking the expression into the actual executable, even if they know it's subject to change. These strategies may work, but they take time to implement, time for users to learn, and induce technical debt as requirements change. This library is meant to cover all the normal C-like expressions, so that you don't have to reinvent one of the oldest wheels on a computer.\n\nHow do I use it?\n--\n\nYou create a new EvaluableExpression, then call \"Evaluate\" on it.\n\n```go\n\texpression, err := govaluate.NewEvaluableExpression(\"10 \u003e 0\");\n\tresult, err := expression.Evaluate(nil);\n\t// result is now set to \"true\", the bool value.\n```\n\nCool, but how about with parameters?\n\n```go\n\texpression, err := govaluate.NewEvaluableExpression(\"foo \u003e 0\");\n\n\tparameters := make(map[string]interface{}, 8)\n\tparameters[\"foo\"] = -1;\n\n\tresult, err := expression.Evaluate(parameters);\n\t// result is now set to \"false\", the bool value.\n```\n\nThat's cool, but we can almost certainly have done all that in code. What about a complex use case that involves some math?\n\n```go\n\texpression, err := govaluate.NewEvaluableExpression(\"(requests_made * requests_succeeded / 100) \u003e= 90\");\n\n\tparameters := make(map[string]interface{}, 8)\n\tparameters[\"requests_made\"] = 100;\n\tparameters[\"requests_succeeded\"] = 80;\n\n\tresult, err := expression.Evaluate(parameters);\n\t// result is now set to \"false\", the bool value.\n```\n\nOr maybe you want to check the status of an alive check (\"smoketest\") page, which will be a string?\n\n```go\n\texpression, err := govaluate.NewEvaluableExpression(\"http_response_body == 'service is ok'\");\n\n\tparameters := make(map[string]interface{}, 8)\n\tparameters[\"http_response_body\"] = \"service is ok\";\n\n\tresult, err := expression.Evaluate(parameters);\n\t// result is now set to \"true\", the bool value.\n```\n\nThese examples have all returned boolean values, but it's equally possible to return numeric ones.\n\n```go\n\texpression, err := govaluate.NewEvaluableExpression(\"(mem_used / total_mem) * 100\");\n\n\tparameters := make(map[string]interface{}, 8)\n\tparameters[\"total_mem\"] = 1024;\n\tparameters[\"mem_used\"] = 512;\n\n\tresult, err := expression.Evaluate(parameters);\n\t// result is now set to \"50.0\", the float64 value.\n```\n\nYou can also do date parsing, though the formats are somewhat limited. Stick to RF3339, ISO8061, unix date, or ruby date formats. If you're having trouble getting a date string to parse, check the list of formats actually used: [parsing.go:248](https://github.com/Knetic/govaluate/blob/0580e9b47a69125afa0e4ebd1cf93c49eb5a43ec/parsing.go#L258).\n\n```go\n\texpression, err := govaluate.NewEvaluableExpression(\"'2014-01-02' \u003e '2014-01-01 23:59:59'\");\n\tresult, err := expression.Evaluate(nil);\n\n\t// result is now set to true\n```\n\nExpressions are parsed once, and can be re-used multiple times. Parsing is the compute-intensive phase of the process, so if you intend to use the same expression with different parameters, just parse it once. Like so;\n\n```go\n\texpression, err := govaluate.NewEvaluableExpression(\"response_time \u003c= 100\");\n\tparameters := make(map[string]interface{}, 8)\n\n\tfor {\n\t\tparameters[\"response_time\"] = pingSomething();\n\t\tresult, err := expression.Evaluate(parameters)\n\t}\n```\n\nThe normal C-standard order of operators is respected. When writing an expression, be sure that you either order the operators correctly, or use parenthesis to clarify which portions of an expression should be run first.\n\nEscaping characters\n--\n\nSometimes you'll have parameters that have spaces, slashes, pluses, ampersands or some other character\nthat this library interprets as something special. For example, the following expression will not\nact as one might expect:\n\n\t\"response-time \u003c 100\"\n\nAs written, the library will parse it as \"[response] minus [time] is less than 100\". In reality,\n\"response-time\" is meant to be one variable that just happens to have a dash in it.\n\nThere are two ways to work around this. First, you can escape the entire parameter name:\n\n \t\"[response-time] \u003c 100\"\n\nOr you can use backslashes to escape only the minus sign.\n\n\t\"response\\\\-time \u003c 100\"\n\nBackslashes can be used anywhere in an expression to escape the very next character. Square bracketed parameter names can be used instead of plain parameter names at any time.\n\nFunctions\n--\n\nYou may have cases where you want to call a function on a parameter during execution of the expression. Perhaps you want to aggregate some set of data, but don't know the exact aggregation you want to use until you're writing the expression itself. Or maybe you have a mathematical operation you want to perform, for which there is no operator; like `log` or `tan` or `sqrt`. For cases like this, you can provide a map of functions to `NewEvaluableExpressionWithFunctions`, which will then be able to use them during execution. For instance;\n\n```go\n\tfunctions := map[string]govaluate.ExpressionFunction {\n\t\t\"strlen\": func(args ...interface{}) (interface{}, error) {\n\t\t\tlength := len(args[0].(string))\n\t\t\treturn (float64)(length), nil\n\t\t},\n\t}\n\n\texpString := \"strlen('someReallyLongInputString') \u003c= 16\"\n\texpression, _ := govaluate.NewEvaluableExpressionWithFunctions(expString, functions)\n\n\tresult, _ := expression.Evaluate(nil)\n\t// result is now \"false\", the boolean value\n```\n\nFunctions can accept any number of arguments, correctly handles nested functions, and arguments can be of any type (even if none of this library's operators support evaluation of that type). For instance, each of these usages of functions in an expression are valid (assuming that the appropriate functions and parameters are given):\n\n```go\n\"sqrt(x1 ** y1, x2 ** y2)\"\n\"max(someValue, abs(anotherValue), 10 * lastValue)\"\n```\n\nFunctions cannot be passed as parameters, they must be known at the time when the expression is parsed, and are unchangeable after parsing.\n\nAccessors\n--\n\nIf you have structs in your parameters, you can access their fields and methods in the usual way. For instance, given a struct that has a method \"Echo\", present in the parameters as `foo`, the following is valid:\n\n\t\"foo.Echo('hello world')\"\n\nFields are accessed in a similar way. Assuming `foo` has a field called \"Length\":\n\n\t\"foo.Length \u003e 9000\"\n\nAccessors can be nested to any depth, like the following\n\n\t\"foo.Bar.Baz.SomeFunction()\"\n\nHowever it is not _currently_ supported to access values in `map`s. So the following will not work\n\n\t\"foo.SomeMap['key']\"\n\nThis may be convenient, but note that using accessors involves a _lot_ of reflection. This makes the expression about four times slower than just using a parameter (consult the benchmarks for more precise measurements on your system).\nIf at all reasonable, the author recommends extracting the values you care about into a parameter map beforehand, or defining a struct that implements the `Parameters` interface, and which grabs fields as required. If there are functions you want to use, it's better to pass them as expression functions (see the above section). These approaches use no reflection, and are designed to be fast and clean.\n\nWhat operators and types does this support?\n--\n\n* Modifiers: `+` `-` `/` `*` `\u0026` `|` `^` `**` `%` `\u003e\u003e` `\u003c\u003c`\n* Comparators: `\u003e` `\u003e=` `\u003c` `\u003c=` `==` `!=` `=~` `!~`\n* Logical ops: `||` `\u0026\u0026`\n* Numeric constants, as 64-bit floating point (`12345.678`)\n* String constants (single quotes: `'foobar'`)\n* Date constants (single quotes, using any permutation of RFC3339, ISO8601, ruby date, or unix date; date parsing is automatically tried with any string constant)\n* Boolean constants: `true` `false`\n* Parenthesis to control order of evaluation `(` `)`\n* Arrays (anything separated by `,` within parenthesis: `(1, 2, 'foo')`)\n* Prefixes: `!` `-` `~`\n* Ternary conditional: `?` `:`\n* Null coalescence: `??`\n\nSee [MANUAL.md](https://github.com/Knetic/govaluate/blob/master/MANUAL.md) for exacting details on what types each operator supports.\n\nTypes\n--\n\nSome operators don't make sense when used with some types. For instance, what does it mean to get the modulo of a string? What happens if you check to see if two numbers are logically AND'ed together?\n\nEveryone has a different intuition about the answers to these questions. To prevent confusion, this library will _refuse to operate_ upon types for which there is not an unambiguous meaning for the operation. See [MANUAL.md](https://github.com/Knetic/govaluate/blob/master/MANUAL.md) for details about what operators are valid for which types.\n\nBenchmarks\n--\n\nIf you're concerned about the overhead of this library, a good range of benchmarks are built into this repo. You can run them with `go test -bench=.`. The library is built with an eye towards being quick, but has not been aggressively profiled and optimized. For most applications, though, it is completely fine.\n\nFor a very rough idea of performance, here are the results output from a benchmark run on a 3rd-gen Macbook Pro (Linux Mint 17.1).\n\n```\nBenchmarkSingleParse-12                          1000000              1382 ns/op\nBenchmarkSimpleParse-12                           200000             10771 ns/op\nBenchmarkFullParse-12                              30000             49383 ns/op\nBenchmarkEvaluationSingle-12                    50000000                30.1 ns/op\nBenchmarkEvaluationNumericLiteral-12            10000000               119 ns/op\nBenchmarkEvaluationLiteralModifiers-12          10000000               236 ns/op\nBenchmarkEvaluationParameters-12                 5000000               260 ns/op\nBenchmarkEvaluationParametersModifiers-12        3000000               547 ns/op\nBenchmarkComplexExpression-12                    2000000               963 ns/op\nBenchmarkRegexExpression-12                       100000             20357 ns/op\nBenchmarkConstantRegexExpression-12              1000000              1392 ns/op\nok\n```\n\nAPI Breaks\n--\n\nWhile this library has very few cases which will ever result in an API break, it can (and [has](https://github.com/Knetic/govaluate/releases/tag/2.0.0)) happened. If you are using this in production, vendor the commit you've tested against, or use gopkg.in to redirect your import (e.g., `import \"gopkg.in/Knetic/govaluate.v2\"`). Master branch (while infrequent) _may_ at some point contain API breaking changes, and the author will have no way to communicate these to downstreams, other than creating a new major release.\n\nReleases will explicitly state when an API break happens, and if they do not specify an API break it should be safe to upgrade.\n\nLicense\n--\n\nThis project is licensed under the MIT general use license. You're free to integrate, fork, and play with this code as you feel fit without consulting the author, as long as you provide proper credit to the author in your works.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinuxerwang%2Fgovaluate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flinuxerwang%2Fgovaluate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinuxerwang%2Fgovaluate/lists"}