{"id":13411593,"url":"https://github.com/barweiss/go-tuple","last_synced_at":"2026-01-18T09:16:13.266Z","repository":{"id":42500970,"uuid":"441312893","full_name":"barweiss/go-tuple","owner":"barweiss","description":"Go 1.18+ generic tuple","archived":false,"fork":false,"pushed_at":"2025-08-09T10:46:32.000Z","size":75,"stargazers_count":94,"open_issues_count":0,"forks_count":5,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-09T12:22:37.181Z","etag":null,"topics":["golang","golang-package","tuple-library","tuples"],"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/barweiss.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-23T22:51:49.000Z","updated_at":"2025-08-09T10:46:34.000Z","dependencies_parsed_at":"2024-06-18T18:40:12.413Z","dependency_job_id":"354b3a34-deb7-44f0-b21b-bd0ff2977a2c","html_url":"https://github.com/barweiss/go-tuple","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/barweiss/go-tuple","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/barweiss%2Fgo-tuple","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/barweiss%2Fgo-tuple/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/barweiss%2Fgo-tuple/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/barweiss%2Fgo-tuple/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/barweiss","download_url":"https://codeload.github.com/barweiss/go-tuple/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/barweiss%2Fgo-tuple/sbom","scorecard":{"id":226453,"data":{"date":"2025-08-11","repo":{"name":"github.com/barweiss/go-tuple","commit":"a6c1a9b8cb8cfc0f3a3244c6cca380540825cd63"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.9,"checks":[{"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":"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":"Code-Review","score":0,"reason":"Found 1/25 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":"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":"Maintained","score":1,"reason":"2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/go.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":"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/go.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/barweiss/go-tuple/go.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/barweiss/go-tuple/go.yml/main?enable=pin","Warn: goCommand not pinned by hash: .github/workflows/go.yml:33","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 goCommand 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":"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":"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE: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":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 20 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"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-17T03:54:45.766Z","repository_id":42500970,"created_at":"2025-08-17T03:54:45.767Z","updated_at":"2025-08-17T03:54:45.767Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28534156,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T00:39:45.795Z","status":"online","status_checked_at":"2026-01-18T02:00:07.578Z","response_time":98,"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":["golang","golang-package","tuple-library","tuples"],"created_at":"2024-07-30T20:01:14.806Z","updated_at":"2026-01-18T09:16:08.247Z","avatar_url":"https://github.com/barweiss.png","language":"Go","funding_links":[],"categories":["数据结构与算法","Data Structures and Algorithms","Generators","Data Integration Frameworks"],"sub_categories":["杂项数据结构和算法","Miscellaneous Data Structures and Algorithms"],"readme":"# go-tuple: Generic tuples for Go 1.18+.\n\n[![Go](https://github.com/barweiss/go-tuple/actions/workflows/go.yml/badge.svg)](https://github.com/barweiss/go-tuple/actions/workflows/go.yml)\n[![Coverage Status](https://coveralls.io/repos/github/barweiss/go-tuple/badge.svg)](https://coveralls.io/github/barweiss/go-tuple)\n[![Go Report Card](https://goreportcard.com/badge/github.com/barweiss/go-tuple)](https://goreportcard.com/report/github.com/barweiss/go-tuple)\n[![Go Reference](https://pkg.go.dev/badge/github.com/barweiss/go-tuple.svg)](https://pkg.go.dev/github.com/barweiss/go-tuple)\n[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)\n\nGo 1.18+ tuple implementation.\n\nUse tuples to store 1 or more values without needing to write a custom struct.\n\n```go\ntup := tuple.New2(5, \"hi!\")\nfmt.Println(tup.V1) // Outputs 5.\nfmt.Println(tup.V2) // Outputs \"hi!\".\n```\n\nTuples come in various sizes, from 1 to 9 elements.\n\n```go\nlongerTuple := tuple.New5(\"this\", \"is\", \"one\", \"long\", \"tuple\")\n```\n\nTuples can be used as slice or array items, map keys or values, and as channel payloads:\n\n```go\n// Map holding tuples.\ntupInMap := make(map[tuple.T2[string, string]]Person)\ntupInMap[tuple.New2(\"John\", \"Doe\")] = Person{\n\tFirstName: \"John\",\n\tLastName: \"Doe\",\n\t// ...\n}\n\n// Channel holding tuples.\ntupInChan := make(chan tuple.T2[string, error])\ngo func() {\n\tdefer close(tupInChan)\n\ttupInChan \u003c- tuple.New2(os.Getwd())\n}()\nfmt.Print(\u003c-tupInChan)\n```\n\n# Features\n\n## Create tuples from function calls\n\n```go\nfunc vals() (int, string) {\n    return 5, \"hi!\"\n}\n\nfunc main() {\n    tup := tuple.New2(vals())\n    fmt.Println(tup.V1)\n    fmt.Println(tup.V2)\n}\n```\n\n## Forward tuples as function arguments\n\n```go\nfunc main() {\n    tup := tuple.New2(5, \"hi!\")\n    printValues(tup.Values())\n}\n\nfunc printValues(a int, b string) {\n    fmt.Println(a)\n    fmt.Println(b)\n}\n```\n\n## Access tuple values\n\n```go\ntup := tuple.New2(5, \"hi!\")\na, b := tup.Values()\n```\n\n## JSON Marshalling\n\nTuples are marshalled and unmarshalled as JSON arrays.\n\n```go\ntype User struct {\n\tName string `json:\"name\"`\n\tAge  int    `json:\"age,omitempty\"`\n}\n\ntype MyJSON struct {\n\tUsers []tuple.T2[string, User] `json:\"users\"`\n}\n\nfunc main() {\n\tdata := MyJSON{\n\t\tUsers: []tuple.T2[string, User]{\n\t\t\ttuple.New2(\"foo\", User{Name: \"foo\", Age: 42}),\n\t\t\ttuple.New2(\"bar\", User{Name: \"bar\", Age: 21}),\n\t\t\ttuple.New2(\"baz\", User{Name: \"baz\"}),\n\t\t},\n\t}\n\n\tmarshalled, _ := json.Marshal(data)\n\tfmt.Printf(\"%s\\n\", string(marshalled))\n\t// Outputs: {\"users\":[[\"foo\",{\"name\":\"foo\",\"age\":42}],[\"bar\",{\"name\":\"bar\",\"age\":21}],[\"baz\",{\"name\":\"baz\"}]]}\n}\n```\n\n## Comparison\n\nTuples are compared from the first element to the last.\nFor example, the tuple `[1 2 3]` is greater than `[1 2 4]` but less than `[2 2 2]`.\n\n```go\nfmt.Println(tuple.Equal3(tuple.New3(1, 2, 3), tuple.New3(3, 3, 3))) // false.\nfmt.Println(tuple.LessThan3(tuple.New3(1, 2, 3), tuple.New3(3, 2, 1))) // true.\n\ntups := []tuple.T3{\n    tuple.New3(\"foo\", 2, -23),\n    tuple.New3(\"foo\", 72, 15),\n    tuple.New3(\"bar\", -4, 43),\n}\nsort.Slice(tups, func (i, j int) {\n    return tuple.LessThan3(tups[i], tups[j])\n})\n\nfmt.Println(tups) // [[\"bar\", -4, 43], [\"foo\", 2, -23], [\"foo\", 72, 15]].\n```\n\n---\n\n**NOTE**\n\nIn order to compare tuples, all tuple elements must match `constraints.Ordered`.\n\nSee [Custom comparison](#custom-comparison) in order to see how to compare tuples\nwith arbitrary element values.\n\n---\n\n### Comparison result\n\n```go\n// Compare* functions return an OrderedComparisonResult value.\nresult := tuple.Compare3(tuple.New3(1, 2, 3), tuple.New3(3, 2, 1))\n\n// OrderedComparisonResult values are wrapped integers.\nfmt.Println(result) // -1\n\n// OrderedComparisonResult expose various method to see the result\n// in a more readable way.\nfmt.Println(result.GreaterThan()) // false\n```\n\n### Custom comparison\n\nThe package provides the `CompareC` comparison functions varation in order to compare tuples of complex\ncomparable types.\n\nFor a type to be comparable, it must match the `Comparable` or `Equalable` constraints.\n\n```go\ntype Comparable[T any] interface {\n\tCompareTo(guest T) OrderedComparisonResult\n}\n\ntype Equalable[T any] interface {\n\tEqual(guest T) bool\n}\n```\n\n```go\ntype person struct {\n\tname string\n\tage  int\n}\n\nfunc (p person) CompareTo(guest person) tuple.OrderedComparisonResult {\n\tif p.name \u003c guest.name {\n\t\treturn -1\n\t}\n\tif p.name \u003e guest.name {\n\t\treturn 1\n\t}\n\treturn 0\n}\n\nfunc main() {\n\ttup1 := tuple.New2(person{name: \"foo\", age: 20}, person{name: \"bar\", age: 24})\n\ttup2 := tuple.New2(person{name: \"bar\", age: 20}, person{name: \"baz\", age: 24})\n\n\tfmt.Println(tuple.LessThan2C(tup1, tup2)) // true.\n}\n```\n\nIn order to call the complex types variation of the comparable functions, **all** tuple types must match the `Comparable` constraint.\n\nWhile this is not ideal, this a known inconvenience given the current type parameters capabilities in Go.\nSome solutions have been porposed for this issue ([lesser](https://github.com/lelysses/lesser), for example, beatifully articulates the issue),\nbut they still demand features that are not yet implemented by the language.\n\nOnce the language will introduce more convenient ways for generic comparisons, this package will adopt it.\n\n## Formatting\n\nTuples implement the `Stringer` and `GoStringer` interfaces.\n\n```go\nfmt.Printf(\"%s\\n\", tuple.New2(\"hello\", \"world\"))\n// Output:\n// [\"hello\" \"world\"]\n\nfmt.Printf(\"%#v\\n\", tuple.New2(\"hello\", \"world\"))\n// Output:\n// tuple.T2[string, string]{V1: \"hello\", V2: \"world\"}\n```\n\n# Notes\n\nThe tuple code and test code are generated by the `scripts/gen/main.go` script.\n\nGeneration works by reading `tuple.tpl` and `tuple_test.tpl` using Go's `text/template` engine.\n`tuple.tpl` and `tuple_test.tpl` contain the templated content of a generic tuple class, with variable number of elements.\n\n# Contributing\n\nPlease feel free to contribute to this project by opening issues or creating pull-requests.\nHowever, keep in mind that generic type features for Go are still in their early stages, so there might\nnot be support from the language to your requested feature.\n\nAlso keep in mind when contributing to keep the compilation time and performance of this package fast.\n\nFeel free to contact me at [barw.code@gmail.com](mailto:barw.code@gmail.com) for questions or suggestions!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbarweiss%2Fgo-tuple","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbarweiss%2Fgo-tuple","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbarweiss%2Fgo-tuple/lists"}