{"id":18425585,"url":"https://github.com/atomix/go-sdk","last_synced_at":"2025-08-19T03:06:35.858Z","repository":{"id":42460383,"uuid":"185415744","full_name":"atomix/go-sdk","owner":"atomix","description":"Atomix 4 Go client","archived":false,"fork":false,"pushed_at":"2023-06-27T07:09:29.000Z","size":4799,"stargazers_count":11,"open_issues_count":10,"forks_count":7,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-08-18T12:59:50.125Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/atomix.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSES/Apache-2.0.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2019-05-07T14:12:55.000Z","updated_at":"2025-07-31T06:50:07.000Z","dependencies_parsed_at":"2023-07-13T15:26:05.884Z","dependency_job_id":null,"html_url":"https://github.com/atomix/go-sdk","commit_stats":null,"previous_names":["atomix/go-client","atomix/atomix-go-client","atomix/atomix-go"],"tags_count":57,"template":false,"template_full_name":null,"purl":"pkg:github/atomix/go-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomix%2Fgo-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomix%2Fgo-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomix%2Fgo-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomix%2Fgo-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/atomix","download_url":"https://codeload.github.com/atomix/go-sdk/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomix%2Fgo-sdk/sbom","scorecard":{"id":215333,"data":{"date":"2025-08-11","repo":{"name":"github.com/atomix/go-sdk","commit":"e4734187a7601aa732700242eda8f8e3be931f24"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.8,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build.yml:1","Warn: no topLevel permission defined: .github/workflows/release.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/atomix/go-sdk/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/atomix/go-sdk/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/atomix/go-sdk/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/atomix/go-sdk/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/atomix/go-sdk/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/atomix/go-sdk/release.yml/master?enable=pin","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSES/Apache-2.0.txt:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSES/Apache-2.0.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":0,"reason":"12 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2022-0969 / GHSA-69cg-p879-7622","Warn: Project is vulnerable to: GO-2022-1144 / GHSA-xrjj-mj9h-534m","Warn: Project is vulnerable to: GO-2023-1571 / GHSA-vvpx-j8f3-3w6h","Warn: Project is vulnerable to: GO-2023-1988 / GHSA-2wrh-6pvc-2jm9","Warn: Project is vulnerable to: GO-2023-2102 / GHSA-4374-p667-p6c8","Warn: Project is vulnerable to: GO-2023-2153 / GHSA-m425-mq94-257g / GHSA-qppj-fm5r-hxr3","Warn: Project is vulnerable to: GO-2024-2687 / GHSA-4v7x-pqxf-cx7m","Warn: Project is vulnerable to: GO-2024-3333","Warn: Project is vulnerable to: GO-2025-3503 / GHSA-qxp5-gwg8-xv66","Warn: Project is vulnerable to: GO-2025-3595 / GHSA-vvgc-356p-c3xw","Warn: Project is vulnerable to: GO-2022-1059 / GHSA-69ch-w2m2-3vjp","Warn: Project is vulnerable to: GO-2024-2611 / GHSA-8r3f-844c-mc37"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-17T01:33:35.776Z","repository_id":42460383,"created_at":"2025-08-17T01:33:35.776Z","updated_at":"2025-08-17T01:33:35.776Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271093020,"owners_count":24697915,"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-08-19T02:00:09.176Z","response_time":63,"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":[],"created_at":"2024-11-06T05:04:28.421Z","updated_at":"2025-08-19T03:06:35.823Z","avatar_url":"https://github.com/atomix.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!--\nSPDX-FileCopyrightText: 2019-present Open Networking Foundation \u003cinfo@opennetworking.org\u003e\nSPDX-License-Identifier: Apache-2.0 \n--\u003e\n\n[![Snapshot](https://github.com/atomix/go-sdk/actions/workflows/build.yml/badge.svg)](https://github.com/atomix/go-sdk/actions/workflows/build.yml)\n[![Release](https://github.com/atomix/go-sdk/actions/workflows/release.yml/badge.svg)](https://github.com/atomix/go-sdk/actions/workflows/release.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/atomix/go-sdk)](https://goreportcard.com/report/github.com/atomix/go-sdk)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/gojp/goreportcard/blob/master/LICENSE)\n[![GoDoc](https://godoc.org/github.com/atomix/go-sdk?status.svg)](https://godoc.org/github.com/atomix/go-sdk)\n\n# Go Client\n\nThis project provides a [Go] client for [Atomix Cloud].\n\n## Getting Started\n\n### Installation\n\nTo install the Go client, use `go get`:\n\n```bash\n$ GO111MODULE=on go get github.com/atomix/go-sdk\n```\n\n### Usage\n\nTo use the client, import the client API:\n\n```go\nimport \"github.com/atomix/go-sdk/pkg/atomix\"\n```\n\nThe `atomix` package provides functions for working with primitives using the default cluster configuration:\n\n```go\ncounter, err := atomix.GetCounter(context.Background(), \"my-counter\")\n```\n\nTo use a non-default configuration, create a client by calling `NewClient`:\n\n```go\nclient := atomix.NewClient(atomix.WithBrokerPort(8000))\ncounter, err := client.GetCounter(context.Background(), \"my-counter\")\n```\n\nTo create a distributed primitive, call the getter for the desired type, passing the name of the primitive and any\nadditional primitive options:\n\n```go\nlock, err := atomix.GetLock(context.Background(), \"my-lock\")\nif err != nil {\npanic(err)\n}\n```\n\nPrimitive names are shared across all clients for a given _scope_ within a given\n_database_. Any two primitives with the same name in the same scope and stored in the same database reference the same\nstate machine regardless of client locations. So a\n`Lock` call in one container will block will block lock requests from all other containers until unlocked.\n\n```go\nversion, err := lock.Lock(context.Background())\nif err == nil {\n// Lock is acquired with version 'version'\n}\n```\n\nWhen a primitive is no longer in used by the client it can be closed with `Close` to reclaim resources:\n\n```go\nlock.Close(context.Background())\n```\n\n## Counter\n\nThe `Counter` primitive is a distributed counter that supports atomic increment, decrement,\nand check-and-set operations. To create a counter, call `GetCounter` on the database in which\nto create the counter:\n\n```go\nmyCounter, err := atomix.GetCounter(context.Background(), \"my-counter\")\nif err != nil {\n\t...\n}\n\ndefer myCounter.Close(context.Background())\n```\n\n```go\ncount, err := myCounter.Get(context.Background())\nif err != nil {\n\t...\n}\n```\n\n```go\ncount, err = myCounter.Set(context.Background(), 10)\nif err != nil {\n\t...\n}\n```\n\n```go\ncount, err = myCounter.Increment(context.Background(), 1)\nif err != nil {\n\t...\n}\n```\n\n```go\ncount, err = myCounter.Decrement(context.Background(), 10)\nif err !=  nil {\n\t...\n}\n```\n\n## Leader Election\n\nThe `Election` primitive supports distributed leader election. Leader elections are implemented\nusing first-in-first-out, but clients can sort election priority through various operations on\nthe `Election` interface.\n\nTo create an `Election`, call `GetElection` on the database in which to create the election:\n\n```go\nmyElection, err := atomix.GetElection(context.Background(), \"my-election\")\nif err != nil {\n\t...\n}\n\ndefer myElection.Close(context.Background())\n```\n\nEach `Election` object has a globally unique node ID which is used to identify the client and\ncan be read by calling `ID()`:\n\n```go\nid := myElection.ID()\n```\n\nThe election ID is used to differentiate candidates and can be explicitly assigned by specifying a\nsession ID when getting the election instance:\n\n```go\nmyElection, err := atomix.GetElection(context.Background(), \"my-election\", primitive.WithSessionID(\"node-1\"))\n```\n\nThe current election `Term` can be retrieved by calling `GetTerm`:\n\n```go\nterm, err := myElection.GetTerm(context.Background())\nif err != nil {\n\t...\n}\n```\n\nThe `Term` contains the complete state of the election:\n* `Leader` - the current leader ID\n* `Term` - a `uint64` per-leader, globally unique, monotonically increasing epoch for the leader\n* `Candidates` - a sequence of all candidates participating in the election in priority order,\n  including the current leader\n\nTo enter the client into the election, call `Enter`:\n\n```go\nterm, err = myElection.Enter(context.Background())\nif err != nil {\n\t...\n}\n```\n\nThe `Enter` call will return the resulting `Term` struct which can be used to determine whether the\nclient won the election:\n\n```go\nif term.Leader == myElection.ID() {\n\t// This node is the leader\n}\n```\n\nClients can leave the election by calling `Leave`:\n\n```go\nerr = myElection.Leave(context.Background())\nif err != nil {\n\t...\n}\n```\n\nWhen the leader leaves an election, a new leader will be elected. The `Watch` method can be used to\nwatch the election for changes. When the leader or candidates changes, an event will be published\nto all watchers.\n\n```go\nch := make(chan election.Event)\nerr := myElection.Watch(context.Background(), ch)\nfor event := range ch {\n    ...\n}\n```\n\n## IndexedMap\n\n## List\n\n## Lock\n\nThe `Lock` primitive is a distributed lock that provides lock version numbers for fencing.\nTo create a lock, call `GetLock` on the database in which to create the lock.\n\n_Note that it's recommended distributed locking be used with a strongly consistent\ndatabase that implements a protocol like `raft`.\n\n```go\nmyLock, err := atomix.GetLock(context.Background(), \"my-lock\")\nif err != nil {\n\t...\n}\n\ndefer myLock.Close(context.Background())\n```\n\nTo acquire the lock, call `Lock`:\n\n```go\nversion, err := myLock.Lock(context.Background())\nif err != nil {\n\t...\n}\n```\n\nIf the lock is currently held by another client (or another `Lock` instance owned by the\ncurrent client), the `Lock()` call will block until the lock is `Unlock`ed by the owning\nclient. A timeout can be provided by the `Context`:\n\n```go\nctx := context.WithTimeout(context.Background(), 10 * time.Second)\nversion, err := myLock.Lock(ctx)\nif err != nil {\n\t...\n}\n```\n\nSuccessful calls to `Lock()` return a `uint64` lock version number. The lock version number\nis guaranteed to be unique and monotonically increasing, so it's suitable for fencing and\noptimistic locking.\n\nTo determine whether the lock is currently held by any client, call `IsLocked`:\n\n```go\nlocked, err := myLock.IsLocked(context.Background())\nif err != nil {\n\t...\n}\n```\n\nA lock version number can also be passed using `WithVersion` to determine whether the\nlock is held by an owner with the given version number:\n\n```go\nlocked, err = myLock.IsLocked(context.Background(), atomixlock.WithVersion(version))\nif err != nil {\n\t...\n}\n```\n\nOnce the client has finished with the lock, unlock it by calling `Unlock`:\n\n```go\nunlocked, err := myLock.Unlock(context.Background())\nif err != nil {\n\t...\n}\n```\n\nClients can also release any process's lock by passing the owner's lock version\nnumber:\n\n```go\nunlocked, err = myLock.Unlock(context.Background(), lock.IfMatch(lock))\nif err != nil {\n\t...\n}\n```\n\n## Map\n\nThe `Map` primitive provides a distributed map that supports concurrency control through optimistic\nlocking. Maps store `string` keys and `[]byte` values, and map entries are represented in return\nvalues as a `KeyValue` object with the following fields:\n* `Key` - the `string` map key\n* `Value` - the `[]byte` entry value\n* `Version` - a monotonically increasing, unique `int64` entry version suitable for use in optimistic locks\n\nTo create a distributed map, get a `Database` and call `GetMap` on the database:\n\n```go\nmyMap, err := atomix.GetMap[string, string](\n\tcontext.Background(), \n\t\"my-map\", \n\t_map.WithKeyType(generic.String()),\n\t_map.WithValueType(generic.String()))\nif err != nil {\n\t...\n}\n\ndefer myMap.Close(context.Background())\n```\n\nTo put a value in a map, call `Put`:\n\n```go\nentry, err := myMap.Put(context.Background(), \"foo\", \"bar\")\nif err != nil {\n\t...\n}\n```\n\nThe returned `Entry` contains the metadata for the entry that was written to the map. `Get` also\nreturns the `Entry`:\n\n```go\nentry, err = myMap.Get(context.Background(), \"foo\")\nif err != nil {\n\t...\n}\n```\n\nThis entry metadata can be used for optimistic locking when updating the entry using the\n`IfTimestamp` option:\n\n```go\nentry, err := myMap.Update(context.Background(), \"foo\", \"baz\", _map.IfTimestamp(entry.Timestamp))\nif err != nil {\n\t...\n}\n```\n\nTo remove a key from the map, call `Remove`:\n\n```go\nentry, err = myMap.Remove(context.Background(), \"foo\")\nif err != nil {\n\t...\n}\n```\n\nAgain, optimistic locking can be used when removing an entry:\n\n```go\nentry, err = myMap.Remove(context.Background(), \"foo\", _map.IfTimestamp(entry.Timestamp))\nif err != nil {\n\t...\n}\n```\n\nCall `Clear` to remove all entries from the map:\n\n```go\nerr = myMap.Clear(context.Background())\nif err != nil {\n\t...\n}\n```\n\nThe `Watch` method can be used to watch the map for changes. When the map is modified an event will be published to all watchers.\n\n```go\nch := make(chan _map.Event[string, string])\nerr := myMap.Watch(context.Background(), ch)\nfor event := range ch {\n    ...\n}\n```\n\n## Set\n\nThe `Set` primitive is a partitioned distributed set. Set values are stored as `strings`. To create a set, call `GetSet`\non the database in which to create the set:\n\n```go\nmySet, err := atomix.GetSet[string](context.Background(), \"my-set\", set.WithElementType(generic.String()))\nif err != nil {\n    ...\n}\n\ndefer mySet.Close(context.Background())\n```\n\nTo add an element to the set, call `Add`:\n\n```go\nadded, err := mySet.Add(context.Background(), \"foo\")\nif err != nil {\n    ...\n}\n\n```\n\nTo check if the set contains an element, call `Contains`:\n\n```go\ncontains, err := mySet.Contains(context.Background(), \"foo\")\nif err != nil {\n    ...\n}\n\n```\n\nAnd to remove an element from the set, call `Remove`:\n\n```go\nremoved, err := mySet.Remove(context.Background(), \"foo\")\nif err != nil {\n    ...\n}\n\n```\n\nOr to remove all elements from the set, call `Clear`:\n\n```go\nerr := mySet.Clear(context.Background())\nif err != nil {\n    ...\n}\n```\n\nThe `Watch` method can be used to watch the set for changes. When an element is added to or removed from the set,\nan event will be published to all watchers.\n\n```go\nch := make(chan set.Event)\nerr := mySet.Watch(context.Background(), ch)\nfor event := range ch {\n    ...\n}\n```\n\n## Value\n\nThe `Value` primitive is a distributed `[]byte` value that supoorts atomic set-and-get and compare-and-set operations.\n\n```go\nmyValue, err := atomix.GetValue[string](context.Background(), \"my-value\", value.WithType(generic.String()))\nif err != nil {\n    ...\n}\n\ndefer myValue.Close(context.Background())\n```\n\nTo set the value call `Set`:\n\n```go\nts, err := myValue.Set(context.Background(), \"Hello world!\")\nif err != nil {\n    ...\n}\n```\n\nTo get the current value use `Get`:\n\n```go\nvalue, ts, err := myValue.Get(context.Background())\nif err != nil {\n    ...\n}\n```\n\nThe `Timestamp` returned by `Get` and `Set` calls contains versioning information that can be used to perform atomic\ncheck-and-set operations using optimistic locking:\n\n```go\nif value == \"Hello world!\" {\n    _, err := myValue.Set(context.Background(), \"Goodbye world.\", value.IfTimestamp(ts))\n}\n```\n\nThe `Watch` method can be used to watch the value for changes. Each time the value is updated, an event will be\npublished to all watchers.\n\n```go\nch := make(chan value.Event)\nerr := myValue.Watch(context.Background(), ch)\nfor event := range ch {\n    ...\n}\n```\n\n[Go]: https://golang.org\n[Atomix Cloud]: https://atomix.io\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatomix%2Fgo-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fatomix%2Fgo-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatomix%2Fgo-sdk/lists"}