{"id":16948376,"url":"https://github.com/chavacava/dbc4go","last_synced_at":"2025-07-26T07:10:51.220Z","repository":{"id":57481725,"uuid":"111184438","full_name":"chavacava/dbc4go","owner":"chavacava","description":"Design by Contract for Go","archived":false,"fork":false,"pushed_at":"2025-03-29T20:05:54.000Z","size":1275,"stargazers_count":10,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-29T21:20:19.622Z","etag":null,"topics":["code-generation","design-by-contract","golang","runtime-verification"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chavacava.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/funding.yaml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"buy_me_a_coffee":"salvadorca5"}},"created_at":"2017-11-18T07:03:22.000Z","updated_at":"2025-03-15T10:54:49.000Z","dependencies_parsed_at":"2024-12-28T18:18:28.788Z","dependency_job_id":"1585a9b7-6830-4d88-96dc-765d700c6cee","html_url":"https://github.com/chavacava/dbc4go","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/chavacava/dbc4go","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chavacava%2Fdbc4go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chavacava%2Fdbc4go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chavacava%2Fdbc4go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chavacava%2Fdbc4go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chavacava","download_url":"https://codeload.github.com/chavacava/dbc4go/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chavacava%2Fdbc4go/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267133958,"owners_count":24040789,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-26T02:00:08.937Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["code-generation","design-by-contract","golang","runtime-verification"],"created_at":"2024-10-13T21:50:35.383Z","updated_at":"2025-07-26T07:10:51.210Z","avatar_url":"https://github.com/chavacava.png","language":"Go","funding_links":["https://buymeacoffee.com/salvadorca5"],"categories":[],"sub_categories":[],"readme":"[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n# dbc4go\n\n[Design by Contract\u0026trade;](https://en.wikipedia.org/wiki/Design_by_contract) for GO is a code generator that takes GO code annotated with contracts and generates code that enforces those contracts at runtime.  \nContracts are embedded into comments, therefore code annotated with contracts is still valid GO code.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./assets/mascots.jpg\" alt=\"\" width=\"300\"\u003e\n  \u003cbr\u003e\n  Logo by Eze\n\u003c/p\u003e\n\nA simple example: imagine you have a `counter` type like the following\n\n```go\ntype Counter struct {\n\tvalue int\n}\n\n// IncrementBy increments the counter value by n.\nfunc (c *Counter) IncrementBy(n int) {\n\tc.value += n\n}\n```\nYou can add a contract to the `IncrementBy` method to enforce that the resulting value of the counter is actually incremented by `n` at the end of method's execution:\n\n```go\n// IncrementBy increments the counter value by n.\n//\n// Contract:\n//   - ensures value is incremented by n: c.value == @old{c.value} + n\nfunc (c *Counter) IncrementBy(n int) {\n\tc.value += n\n}\n```\nAs is, the contract you added has no effect on your code other than better documenting it.\nBut if you run `dbc4go` on the source file (let's say `counter.go`) \n\n```\n$ dbc4go -i counter.go \n```\nyou will get the following code:\n\n```go\ntype Counter struct {\n\tvalue int\n}\n\n// Increment increments the counter value by a n.\n//\n// Contract:\n//   - ensures value is incremented by n: c.value == @old{c.value} + n\nfunc (c *Counter) IncrementBy(n int) {\n\t{ // Open contract scope\n\t\t// Function's contracts\n\t\told_1 := c.value\n\t\tdefer func() {\n\t\t\tif !(c.value == old_1+n) {\n\t\t\t\tpanic(\"function didn't ensure value is incremented by n\")\n\t\t\t}\n\t\t}()\n\t} // Close contract scope\n\n\tc.value += n\n}\n```\nAs you can see, `dbc4go` instrumented the original code by adding a whole block of statements at the beginning of the method's body.\nThe new code block implements the checking of the contract you wrote in the documentation of the method.\nNow, when the instrumented version of your code is executed, the contract will be enforced, and if the contract is not respected the method will panic.\n\nFor further information on how to write contracts you can read the section [Available contract clauses](#available-contract-clauses) below and check the [examples](./examples/).\n\nYou might still wonder how this can be useful for you.\nWell, one thing you can do is execute your tests on the instrumented version of your code.\nYou could, for example, use `go generate` to obtain an instrumented version of your files and then run `go test`.\nLike that, tests and contracts will combine to provide you more chances to find bugs. \n\nThis project uses contracts itself! Check the source code and the `Makefile` to see how.\n\nThe article [Design by Contract](https://se.inf.ethz.ch/~meyer/publications/old/dbc_chapter.pdf) by Bertrand Meyer provides a complete and clear explanation of the idea. \n\n# Install\nJust grab the executable corresponding to your platform from the releases page (here on the right ----\u003e )\n\n# Usage\n\n```\nUsage of dbc4go:\n  -i string\n        input source file (defaults to stdin)\n  -o string\n        output file (defaults to stdout)\n```\n\n## Available contract clauses\n\n### `requires`\n\n`requires` contract clauses describe **pre-conditions** imposed by functions/methods.     \n\nSyntax:\n\n`requires`(_description_`:`)? _GO Boolean expression_\n\nAs you can see in the example below, the _GO Boolean expression_ must be a valid GO Boolean expression as it will be used as the condition in an `if-then` statement.\n\nThe expression can make reference to any identifier available in the scope at the beginning of the annotated function (for example: function parameters, method receiver, global variables, other functions)\n\nContract clauses must be organized as a list under a contract declaration of the form `Contract:`.\n\nExample:\n\n```go\nconst maxAuthorizedSpeed = 350\n\n// NewCar returns a Car struct.\n//\n// Contract:\n//   - requires more than 2 wheels: wheels \u003e 2\n//   - requires wheelsDrive \u003c= wheels \u0026\u0026 wheelsDrive \u003e= 2 \u0026\u0026 wheelsDrive%2 == 0 \n//   - requires maxSpeedKmh \u003e 0 \u0026\u0026 maxSpeedKmh \u003c= maxAuthorizedSpeed\n//   - requires manufacturer != \"\"\nfunc NewCar(wheels int, wheelsDrive int, maxSpeedKmh int, manufacturer string) Car { ... }\n```\n\n_Short-statements_ are supported as part of _GO Boolean expression_, therefore it's okay to write a contract like the following:\n\n```go\n// Accelerate the car.\n//\n// Contract:\n//   - requires delta \u003e 0\n//   - requires targetSpeed := c.speed + delta; targetSpeed \u003c= c.maxSpeedKmh\nfunc (c *Car) Accelerate(delta int) { ... }\n```\n### `ensures`\n\n`ensures` contract clauses describes **post-conditions** of a function/method.     \n\nSyntax:\n\n`ensures` (_description_`:`)? _GO Boolean expression_\n\nAs for `ensure` clauses, the expression can make reference to any identifier available in the scope at the beginning of the annotated function (for example: function parameters, method receiver, global variables, other functions).\n\nAdditionally, expressions in `ensure` clauses can use the `@old` operator to refer to the state of variables as it was just before the execution of the function.\n\nExample:\n\n```go\n// Accelerate the car.\n//\n// Contract:\n//   - requires delta \u003e 0\n//   - requires c.speed + delta \u003c= c.maxSpeedKmh\n//   - ensures c.speed == @old{c.speed}+delta\nfunc (c *Car) Accelerate(delta int) { ... }\n```\n\nLimitations of `@old`: \n1. at most one `@old` expression in the short-statement and one in the Boolean expression.\n2. `dbc4go` doesn't have type information of expressions inside an `@old` annotation therefore in some cases you need to add type casts to obtain compilable code. For example, to indicate that `@old{someExpression}` is of type `float` you must write `@old{someExpression}.(float)`\n\nAn alternative to `@old` annotations is the use of `let` clauses (see below) thus the previous example could be also written as:\n\n```go\n// Accelerate the car.\n//\n// Contract:\n//   - requires delta \u003e 0\n//   - requires c.speed + delta \u003c= c.maxSpeedKmh\n//   - let initialSpeed := c.speed\n//   - ensures c.speed == initialSpeed+delta\nfunc (c *Car) Accelerate(delta int) { ... }\n```\n### `let`\nCaptures an expression's value into a variable **at the beginning of the function execution**.\nThe variable can be used in `ensures` and `requires`\n\nSyntax:\n\n`let` _id_ `:=` _expression_\n \n_id_ must be a valid GO identifier and _expression_ a valid GO expression in the context of the annotated function.\n\n### `invariant`\n\nDefines an invariant property of a `struct`.\nAn invariant property is a property of the struct that should always hold.\nEvery method attached to the struct can assume the invariants hold and must preserve the invariants.\nInvariants are enforced, materialized as `requires` and `ensures` clauses, on every method attached to the struct.\n\nSyntax:\n\n`invariant` (_description_`:`)? _GO Boolean expression_\n\nThe expression can make reference to any identifier available in the scope of the struct declaration and any _private_ field identifier of the `struct` to which the invariant applies to.\nReferences to fields must be a selector expression of the form `\u003cstruct-name\u003e.\u003cfield-name\u003e` \n\nExamples:\n\n```go\n// Car data-model.\n//\n// Contract:\n//   - invariant Car.speed \u003c= Car.maxSpeedKmh\n//   - invariant Car.speed \u003e= 0\ntype Car struct {\n        maxSpeedKmh int\n        speed       int\n        // other fields ...\n}\n```\n\n```go\n// BankAccount data-model\n//\n// Contract:\n//   - invariant BankAccount.balance \u003e= 0\ntype BankAccount struct {\n        balance float\n        // other fields ...\n}\n```\n\n### `unmodified`\n\nEnforces the function keeps unmodified the given list of expressions.\n\nSyntax:\n\n`unmodified` (_description_`:`)? _expressions list_\n\nExample:\n\n```go\n// Accelerate the car.\n//\n// Contract:\n//   - requires delta \u003e 0\n//   - requires c.speed + delta \u003c= c.maxSpeedKmh\n//   - let initialSpeed := c.speed\n//   - ensures c.speed == initialSpeed+delta\n//   - unmodified c.wheels, c.wheelsDrive, c.maxSpeedKmh, c.manufacturer\nfunc (c *Car) Accelerate(delta int) { ... }\n```\n`unmodified` is just syntax sugar for simplify writing `ensures expr == @old{expr}`\n\n### `import`\n\nIf in your contracts you need to use a package that is not imported by the original source code, then you can import the package with the `import` clause.\n\nSyntax:\n\n`import` _pakage name_\n\nExample:\n\n```go\n// Add element e to container\n//\n// Contract:\n//   - import strings\n//   - requires strings.HasPrefix(e, \"my\")\nfunc (c *Container) Add(e string) { ... }\n```\n\n### The `==\u003e` and `\u003c==\u003e` operators\nThe `==\u003e` (implication) and `\u003c==\u003e` (double implication) allow to write more precise and concise contracts like\n\n```go\n// Accelerate the car.\n//\n// Contract:\n//   - requires delta \u003e 0\n//   - let initialSpeed := c.speed\n//   - ensures initialSpeed + delta \u003c c.maxSpeedKmh ==\u003e c.speed == initialSpeed + delta\n//   - ensures initialSpeed + delta \u003e= c.maxSpeedKmh ==\u003e c.speed == c.maxSpeedKmh \nfunc (c *Car) Accelerate(delta int) { ... }\n```\n\n### The `@forall` operator\n\nThe `@forall` operator allows to write contracts on all the elements of a collection (a `range`-able type)\n\nSyntax:\n\n`@forall` _element_id_ (`@in`|`@indexof`|`@iterating`) _collection_id_`:` _GO Boolean expression_\n\nWhile the syntax `@forall ... @in` shall be used when ranging over elements of the collection; `@forall ... @indexof` shall be used when iterating with an index over the collection and `@iterating` must be used when ranging through an [iterator functions](https://pkg.go.dev/iter#hdr-Iterators).\n\n```go\n// square returs the square of the given integers\n//\n// Contract:\n//   - ensures all returned elements are non-negative: @forall n @in squareds: n \u003e= 0\nfunc square(nums []int) (squareds []int) {\n\t// implementation\n}\n```\n```go\n// square returs the square of the given integers\n//\n// Contract:\n//   - ensures @forall i @indexof nums: squareds[i] == nums[i] * nums[i]\nfunc square(nums []int) (squareds []int) {\n\t// implementation\n}\n```\n\n### The `@exists` operator\n\nThe `@exists` operator allows to write contracts on the elements of a collection (a `range`-able type)\n\nSyntax:\n\n`@exists` _element_id_ (`@in`|`@indexof`|`@iterating`) _collection_id_`:` _GO Boolean expression_\n\nChoosing between `@in`, `@indexof` and `@iterating`  follows the same rules as within the `@forall` operator.\n\n`@forall` and `@exists` operators can be nested with the following syntax:\n\n((`@forall`|`@exists`) _element_id_ (`@in`|`@indexof`) _collection_id_`:`)+ _GO Boolean expression_\n\n### Contract Syntax \n\n`dbc4go` supports three contract syntaxes:\n1. _standard_ syntax, the one introduced in the previous sections,\n2. _raw_ syntax, and\n2. _directive_ syntax \n\nAll three syntaxes have equivalent expressiveness power. \n\nWhile the _raw_ syntax is easier/shorter to write, the _standard_ syntax lets GO tools and IDE to render function and types contracts in a nicer and readable form.\n\n```go\n// Contract in standard syntax\n\n// NewCar returns a Car struct.\n//\n// Contract:\n//  - requires wheels \u003e 2\n//  - requires wheelsDrive \u003c= wheels \u0026\u0026 wheelsDrive \u003e= 2 \u0026\u0026 wheelsDrive%2 == 0\n//  - requires maxSpeedKmh \u003e 0 \u0026\u0026 maxSpeedKmh \u003c= maxAuthorizedSpeed\n//  - requires manufacturer != \"\"\nfunc NewCar(...) {...}\n```\n\n```go\n// Contract in raw syntax\n\n// NewCar returns a Car struct.\n//\n// @requires wheels \u003e 2\n// @requires wheelsDrive \u003c= wheels \u0026\u0026 wheelsDrive \u003e= 2 \u0026\u0026 wheelsDrive%2 == 0\n// @requires maxSpeedKmh \u003e 0 \u0026\u0026 maxSpeedKmh \u003c= maxAuthorizedSpeed\n// @requires manufacturer != \"\"\nfunc NewCar(...) {...}\n```\n_Raw_ syntax doesn't require a contract declaration, and contract clauses can be line-interleaved within non-contractual documentation.\n\n_Directive_ syntax is useful in situations where you need to add a contract clause that will not render in the documentation.\nFor example, if a struct invariant refers to a private field and you don't want to leak the field's name in the documentation you can define the invariant using directive syntax:\n\n```go\n// Contract in directive syntax\n\n// BankAccount represents a bank account.\n//\n//contract:invariant !BankAccount.closed ==\u003e BankAccount.balance \u003e= minBalance\n//contract:invariant !BankAccount.closed ==\u003e BankAccount.balance \u003c= maxBalance\n//contract:invariant BankAccount.closed ==\u003e BankAccount.balance == 0\ntype BankAccount struct {\n\tbalance int  // the balance of the account\n\tclosed  bool // is the account closed?\n}\n```\n(notice there is no blank space between the comment delimiter `//` and the contract clause)\n\n#### Raw syntax summary\n\n`@requires` (_description_`:`)? _GO Boolean expression_\n\n`@ensures` (_description_`:`)? _GO Boolean expression_\n\n`@let` _id_ `:=` _expression_\n\n`@invariant` (_description_`:`)? _GO Boolean expression_\n\n`@unmodified` (_description_`:`)? _identifiers list_\n\n`@import` _pakage name_\n\nYou can **check [these examples](./examples/raw_contracts/)** of code annotated with the raw syntax.\n\n#### Directive syntax summary\n\nContract clauses must respect the directive comment format as defined in the **Syntax** section of [Go Doc Comments](https://tip.golang.org/doc/comment) \n\n`contract:requires` (_description_`:`)? _GO Boolean expression_\n\n`contract:ensures` (_description_`:`)? _GO Boolean expression_\n\n`contract:let` _id_ `:=` _expression_\n\n`contract:invariant` (_description_`:`)? _GO Boolean expression_\n\n`contract:unmodified` (_description_`:`)? _identifiers list_\n\n`contract:import` _pakage name_\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchavacava%2Fdbc4go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchavacava%2Fdbc4go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchavacava%2Fdbc4go/lists"}