{"id":13771688,"url":"https://github.com/alexkohler/prealloc","last_synced_at":"2026-01-16T19:17:24.164Z","repository":{"id":41092685,"uuid":"109629814","full_name":"alexkohler/prealloc","owner":"alexkohler","description":"prealloc is a Go static analysis tool to find slice declarations that could potentially be preallocated.","archived":false,"fork":false,"pushed_at":"2026-01-05T12:24:07.000Z","size":123,"stargazers_count":660,"open_issues_count":3,"forks_count":25,"subscribers_count":5,"default_branch":"master","last_synced_at":"2026-01-08T22:34:39.731Z","etag":null,"topics":["go","golang","prealloc-suggestions","slice","static-analysis","static-analyzer","static-code-analysis"],"latest_commit_sha":null,"homepage":null,"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/alexkohler.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2017-11-06T00:48:14.000Z","updated_at":"2026-01-05T12:24:12.000Z","dependencies_parsed_at":"2024-01-12T21:19:56.135Z","dependency_job_id":"dbc99c2f-86c8-4909-b9e6-aec41a03c64e","html_url":"https://github.com/alexkohler/prealloc","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/alexkohler/prealloc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexkohler%2Fprealloc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexkohler%2Fprealloc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexkohler%2Fprealloc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexkohler%2Fprealloc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexkohler","download_url":"https://codeload.github.com/alexkohler/prealloc/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexkohler%2Fprealloc/sbom","scorecard":{"id":181929,"data":{"date":"2025-08-11","repo":{"name":"github.com/alexkohler/prealloc","commit":"deab4f54fe09416cbe81d29bfa0aee2834346b0c"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.1,"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":"Code-Review","score":7,"reason":"Found 8/11 approved changesets -- score normalized to 7","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":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":"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build-test.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/build-test.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/alexkohler/prealloc/build-test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build-test.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/alexkohler/prealloc/build-test.yml/master?enable=pin","Info:   0 out of   2 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":"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":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"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":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"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 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"}}]},"last_synced_at":"2025-08-16T19:00:04.135Z","repository_id":41092685,"created_at":"2025-08-16T19:00:04.135Z","updated_at":"2025-08-16T19:00:04.135Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28481645,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","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":["go","golang","prealloc-suggestions","slice","static-analysis","static-analyzer","static-code-analysis"],"created_at":"2024-08-03T17:00:54.314Z","updated_at":"2026-01-16T19:17:24.155Z","avatar_url":"https://github.com/alexkohler.png","language":"Go","readme":"# prealloc\n\nprealloc is a Go static analysis tool to find slice declarations that could potentially be preallocated.\n\n## Installation\n\n    go install github.com/alexkohler/prealloc@latest\n\n## Usage\n\nSimilar to other Go static analysis tools (such as golint, go vet), prealloc can be invoked with one or more filenames, directories, or packages named by its import path. Prealloc also supports the `...` wildcard.\n\n    prealloc [flags] files/directories/packages\n\n### Flags\n- **-simple** (default true) - Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them. Setting this to false may increase false positives.\n- **-rangeloops** (default true) - Report preallocation suggestions on range loops.\n- **-forloops** (default false) - Report preallocation suggestions on for loops. This is false by default due to there generally being weirder things happening inside for loops (at least from what I've observed in the Standard Library).\n\n## Purpose\n\nWhile [Go *does* attempt to avoid reallocation by growing the capacity in advance](https://github.com/golang/go/blob/87e48c5afdcf5e01bb2b7f51b7643e8901f4b7f9/src/runtime/slice.go#L100-L112), this sometimes isn't enough for longer slices.  If the size of a slice is known at the time of its creation, it should be specified.\n\nConsider the following benchmark: (this can be found in prealloc_test.go in this repo)\n\n```Go\nimport \"testing\"\n\nfunc BenchmarkNoPreallocate(b *testing.B) {\n\texisting := make([]int64, 10, 10)\n\tb.ResetTimer()\n\tfor i := 0; i \u003c b.N; i++ {\n\t\t// Don't preallocate our initial slice\n\t\tvar init []int64\n\t\tfor _, element := range existing {\n\t\t\tinit = append(init, element)\n\t\t}\n\t}\n}\n\nfunc BenchmarkPreallocate(b *testing.B) {\n\texisting := make([]int64, 10, 10)\n\tb.ResetTimer()\n\tfor i := 0; i \u003c b.N; i++ {\n\t\t// Preallocate our initial slice\n\t\tinit := make([]int64, 0, len(existing))\n\t\tfor _, element := range existing {\n\t\t\tinit = append(init, element)\n\t\t}\n\t}\n}\n```\n\n```Bash\n$ go test -bench=. -benchmem\ngoos: linux\ngoarch: amd64\nBenchmarkNoPreallocate-4   \t 3000000\t       510 ns/op\t     248 B/op\t       5 allocs/op\nBenchmarkPreallocate-4     \t20000000\t       111 ns/op\t      80 B/op\t       1 allocs/op\n```\n\nAs you can see, not preallocating can cause a performance hit, primarily due to Go having to reallocate the underlying array. The pattern benchmarked above is common in Go: declare a slice, then write some sort of range or for loop that appends or indexes into it. The purpose of this tool is to flag slice/loop declarations like the one in `BenchmarkNoPreallocate`.\n\n## Example\n\nSome examples from the Go 1.9.2 source:\n\n```Bash\n$ prealloc go/src/....\narchive/tar/reader_test.go:854 Consider preallocating ss\narchive/zip/zip_test.go:201 Consider preallocating all\ncmd/api/goapi.go:301 Consider preallocating missing\ncmd/api/goapi.go:476 Consider preallocating files\ncmd/asm/internal/asm/endtoend_test.go:345 Consider preallocating extra\ncmd/cgo/main.go:60 Consider preallocating ks\ncmd/cgo/ast.go:149 Consider preallocating pieces\ncmd/compile/internal/ssa/flagalloc.go:64 Consider preallocating oldSched\ncmd/compile/internal/ssa/regalloc.go:719 Consider preallocating phis\ncmd/compile/internal/ssa/regalloc.go:718 Consider preallocating oldSched\ncmd/compile/internal/ssa/regalloc.go:1674 Consider preallocating oldSched\ncmd/compile/internal/ssa/gen/rulegen.go:145 Consider preallocating ops\ncmd/compile/internal/ssa/gen/rulegen.go:145 Consider preallocating ops\ncmd/dist/build.go:893 Consider preallocating all\ncmd/dist/build.go:1246 Consider preallocating plats\ncmd/dist/build.go:1264 Consider preallocating results\ncmd/dist/buildgo.go:59 Consider preallocating list\ncmd/doc/pkg.go:363 Consider preallocating names\ncmd/fix/typecheck.go:219 Consider preallocating b\ncmd/go/internal/base/path.go:34 Consider preallocating out\ncmd/go/internal/get/get.go:175 Consider preallocating out\ncmd/go/internal/load/pkg.go:1894 Consider preallocating dirent\ncmd/go/internal/work/build.go:2402 Consider preallocating absOfiles\ncmd/go/internal/work/build.go:2731 Consider preallocating absOfiles\ncmd/internal/objfile/pe.go:48 Consider preallocating syms\ncmd/internal/objfile/pe.go:38 Consider preallocating addrs\ncmd/internal/objfile/goobj.go:43 Consider preallocating syms\ncmd/internal/objfile/elf.go:35 Consider preallocating syms\ncmd/link/internal/ld/lib.go:1070 Consider preallocating argv\ncmd/vet/all/main.go:91 Consider preallocating pp\ndatabase/sql/sql.go:66 Consider preallocating list\ndebug/macho/file.go:506 Consider preallocating all\ninternal/trace/order.go:55 Consider preallocating batches\nmime/quotedprintable/reader_test.go:191 Consider preallocating outcomes\nnet/dnsclient_unix_test.go:954 Consider preallocating confLines\nnet/interface_solaris.go:85 Consider preallocating ifat\nnet/interface_linux_test.go:91 Consider preallocating ifmat4\nnet/interface_linux_test.go:100 Consider preallocating ifmat6\nnet/internal/socktest/switch.go:34 Consider preallocating st\nos/os_windows_test.go:766 Consider preallocating args\nruntime/pprof/internal/profile/filter.go:77 Consider preallocating lines\nruntime/pprof/internal/profile/profile.go:554 Consider preallocating names\ntext/template/parse/node.go:189 Consider preallocating decl\n```\n\n```Go\n// cmd/api/goapi.go:301\nvar missing []string\nfor feature := range optionalSet {\n\tmissing = append(missing, feature)\n}\n\n// cmd/fix/typecheck.go:219\nvar b []ast.Expr\nfor _, x := range a {\n\tb = append(b, x)\n}\n\n// net/internal/socktest/switch.go:34\nvar st []Stat\nsw.smu.RLock()\nfor _, s := range sw.stats {\n\tns := *s\n\tst = append(st, ns)\n}\nsw.smu.RUnlock()\n\n// cmd/api/goapi.go:301\nvar missing []string\nfor feature := range optionalSet {\n\tmissing = append(missing, feature)\n}\n```\n\nEven if the size the slice is being preallocated to is small, there's still a performance gain to be had in explicitly specifying the capacity rather than leaving it up to `append` to discover that it needs to preallocate. Of course, preallocation doesn't need to be done *everywhere*. This tool's job is just to help suggest places where one should consider preallocating.\n\n## How do I fix prealloc's suggestions?\n\nDuring the declaration of your slice, rather than using the zero value of the slice with `var`, initialize it with Go's built-in `make` function, passing the appropriate type and length. This length will generally be whatever you are ranging over. Fixing the examples from above would look like so:\n\n```Go\n// cmd/api/goapi.go:301\nmissing := make([]string, 0, len(optionalSet))\nfor feature := range optionalSet {\n\tmissing = append(missing, feature)\n}\n\n// cmd/fix/typecheck.go:219\nb := make([]ast.Expr, 0, len(a))\nfor _, x := range a {\n\tb = append(b, x)\n}\n\n// net/internal/socktest/switch.go:34\nst := make([]Stat, 0, len(sw.stats))\nsw.smu.RLock()\nfor _, s := range sw.stats {\n\tns := *s\n\tst = append(st, ns)\n}\nsw.smu.RUnlock()\n\n// cmd/api/goapi.go:301\nmissing := make ([]string, 0, len(optionalSet))\nfor feature := range optionalSet {\n\tmissing = append(missing, feature)\n}\n```\n\nNote: If performance is absolutely critical, it may be more efficient to use `copy` instead of `append` for larger slices. For reference, see the following benchmark:\n```Go\nfunc BenchmarkSize200PreallocateCopy(b *testing.B) {\n\texisting := make([]int64, 200, 200)\n\tb.ResetTimer()\n\tfor i := 0; i \u003c b.N; i++ {\n\t\t// Preallocate our initial slice\n\t\tinit := make([]int64, len(existing))\n\t\tcopy(init, existing)\n\t}\n}\n```\n```\n$ go test -bench=. -benchmem\ngoos: linux\ngoarch: amd64\nBenchmarkSize200NoPreallocate-4     \t  500000\t      3080 ns/op\t    4088 B/op\t       9 allocs/op\nBenchmarkSize200Preallocate-4       \t 1000000\t      1163 ns/op\t    1792 B/op\t       1 allocs/op\nBenchmarkSize200PreallocateCopy-4   \t 2000000\t       807 ns/op\t    1792 B/op\t       1 allocs/op\n```\n\n## TODO\n\n- Configuration on whether or not to run on test files.\n- Globbing support (e.g. prealloc *.go).\n\n## Contributing\n\nPull requests welcome!\n\n## Other static analysis tools\n\nIf you've enjoyed prealloc, take a look at my other static analysis tools!\n- [nakedret](https://github.com/alexkohler/nakedret) - Finds naked returns.\n- [unimport](https://github.com/alexkohler/unimport) - Finds unnecessary import aliases.\n","funding_links":[],"categories":["Linters","Go","Programming Languages"],"sub_categories":["Performance"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexkohler%2Fprealloc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexkohler%2Fprealloc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexkohler%2Fprealloc/lists"}