{"id":"d3200cec-bce7-480d-b239-015c018e5049","shortId":"KfLgye","kind":"skill","title":"go-packages","tagline":"Use when creating Go packages, organizing imports, managing dependencies, or deciding how to structure Go code into packages. Also use when starting a new Go project or splitting a growing codebase into packages, even if the user doesn't explicitly ask about package organization.","description":"# Go Packages and Imports\n\n> **When this skill does NOT apply**: For naming individual identifiers within a package, see [go-naming](../go-naming/SKILL.md). For organizing functions within a single file, see [go-functions](../go-functions/SKILL.md). For configuring linters that enforce import rules, see [go-linting](../go-linting/SKILL.md).\n\n## Package Organization\n\n### Avoid Util Packages\n\nPackage names should describe what the package provides. Avoid generic names\nlike `util`, `helper`, `common` — they obscure meaning and cause import\nconflicts.\n\n```go\n// Good: Meaningful package names\ndb := spannertest.NewDatabaseFromFile(...)\n_, err := f.Seek(0, io.SeekStart)\n\n// Bad: Vague names obscure meaning\ndb := test.NewDatabaseFromFile(...)\n_, err := f.Seek(0, common.SeekStart)\n```\n\nGeneric names can be used as *part* of a name (e.g., `stringutil`) but should\nnot be the entire package name.\n\n### Package Size\n\n| Question | Action |\n|----------|--------|\n| Can you describe its purpose in one sentence? | No → split by responsibility |\n| Do files never share unexported symbols? | Those files could be separate packages |\n| Distinct user groups use different parts? | Split along user boundaries |\n| Godoc page overwhelming? | Split to improve discoverability |\n\n**Do NOT split** just because a file is long, to create single-type packages, or\nif it would create circular dependencies.\n\n> Read [references/PACKAGE-SIZE.md](references/PACKAGE-SIZE.md) when deciding whether to split or combine packages, organizing files within a package, or structuring CLI programs.\n\n---\n\n## Imports\n\nImports are organized in groups separated by blank lines. Standard library\npackages always come first. Use\n[goimports](https://pkg.go.dev/golang.org/x/tools/cmd/goimports) to manage this\nautomatically.\n\n```go\nimport (\n    \"fmt\"\n    \"os\"\n\n    \"github.com/foo/bar\"\n    \"rsc.io/goversion/version\"\n)\n```\n\n**Quick rules:**\n\n| Rule | Guidance |\n|------|----------|\n| Grouping | stdlib first, then external. Extended: stdlib → other → protos → side-effects |\n| Renaming | Avoid unless collision. Rename the most local import. Proto packages get `pb` suffix |\n| Blank imports (`import _`) | Only in `main` packages or tests |\n| Dot imports (`import .`) | Never use, except for circular-dependency test files |\n\n> Read [references/IMPORTS.md](references/IMPORTS.md) when organizing imports with extended grouping, renaming proto packages, or deciding on blank/dot imports.\n\n---\n\n## Avoid init()\n\nAvoid `init()` where possible. When unavoidable, it must be:\n\n1. Completely deterministic\n2. Independent of other `init()` ordering\n3. Free of environment state (env vars, working dir, args)\n4. Free of I/O (filesystem, network, system calls)\n\n**Acceptable uses**: complex expressions that can't be single assignments,\npluggable hooks (e.g., `database/sql` dialects), deterministic precomputation.\n\n> Read [references/PACKAGE-SIZE.md](references/PACKAGE-SIZE.md) when you need to refactor init() into explicit functions or understand acceptable init() uses.\n\n---\n\n## Exit in Main\n\nCall `os.Exit` or `log.Fatal*` **only in `main()`**. All other functions should\nreturn errors.\n\n**Why**: Non-obvious control flow, untestable, `defer` statements skipped.\n\n**Best practice**: Use the `run()` pattern — extract logic into\n`func run() error`, call from `main()` with a single exit point:\n\n```go\nfunc main() {\n    if err := run(); err != nil {\n        log.Fatal(err)\n    }\n}\n```\n\n> Read [references/PACKAGE-SIZE.md](references/PACKAGE-SIZE.md) when implementing the run() pattern, structuring CLI subcommands, or choosing flag naming conventions.\n\n---\n\n## Command-Line Flags\n\n> **Advisory**: Define flags only in `package main`.\n\n- Flag names use `snake_case`: `--output_dir` not `--outputDir`\n- Libraries should accept configuration as parameters, not read flags directly —\n  this keeps them testable and reusable\n- Prefer the standard `flag` package; use `pflag` only when POSIX conventions\n  (double-dash, single-char shortcuts) are required\n\n```go\n// Good: Flag in main, passed as parameter to library\nfunc main() {\n    outputDir := flag.String(\"output_dir\", \".\", \"directory for output files\")\n    flag.Parse()\n    if err := mylib.Generate(*outputDir); err != nil {\n        log.Fatal(err)\n    }\n}\n```\n\n---\n\n## Related Skills\n\n- **Package naming**: See [go-naming](../go-naming/SKILL.md) when choosing package names, avoiding stuttering, or naming exported symbols\n- **Error handling across packages**: See [go-error-handling](../go-error-handling/SKILL.md) when wrapping errors at package boundaries with `%w` vs `%v`\n- **Import linting**: See [go-linting](../go-linting/SKILL.md) when configuring goimports local-prefixes or enforcing import grouping\n- **Global state**: See [go-defensive](../go-defensive/SKILL.md) when replacing `init()` with explicit initialization or avoiding mutable globals","tags":["packages","golang","skills","cxuu","agent-skills","ai-agent","ai-assistant","claude","claude-code","codex","cursor","llm"],"capabilities":["skill","source-cxuu","skill-go-packages","topic-agent-skills","topic-ai-agent","topic-ai-assistant","topic-claude","topic-claude-code","topic-codex","topic-cursor","topic-golang","topic-llm"],"categories":["golang-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/cxuu/golang-skills/go-packages","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add cxuu/golang-skills","source_repo":"https://github.com/cxuu/golang-skills","install_from":"skills.sh"}},"qualityScore":"0.491","qualityRationale":"deterministic score 0.49 from registry signals: · indexed on github topic:agent-skills · 82 github stars · SKILL.md body (4,871 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-02T12:55:18.928Z","embedding":null,"createdAt":"2026-04-18T22:13:19.629Z","updatedAt":"2026-05-02T12:55:18.928Z","lastSeenAt":"2026-05-02T12:55:18.928Z","tsv":"'/foo/bar':281 '/go-defensive/skill.md':644 '/go-error-handling/skill.md':610 '/go-functions/skill.md':81 '/go-linting/skill.md':93,627 '/go-naming/skill.md':69,590 '/golang.org/x/tools/cmd/goimports)':270 '/goversion/version':284 '0':130,141 '1':364 '2':367 '3':373 '4':383 'accept':391,422,519 'across':603 'action':166 'advisori':501 'along':198 'also':22 'alway':263 'appli':57 'arg':382 'ask':44 'assign':400 'automat':274 'avoid':96,107,302,353,355,595,652 'bad':132 'best':451 'blank':258,315 'blank/dot':351 'boundari':200,616 'call':390,428,463 'case':512 'caus':118 'char':549 'choos':493,592 'circular':228,332 'circular-depend':331 'cli':248,490 'code':19 'codebas':34 'collis':304 'combin':239 'come':264 'command':498 'command-lin':497 'common':113 'common.seekstart':142 'complet':365 'complex':393 'configur':83,520,629 'conflict':120 'control':445 'convent':496,543 'could':187 'creat':6,218,227 'dash':546 'database/sql':404 'db':126,137 'decid':14,234,349 'defens':643 'defer':448 'defin':502 'depend':12,229,333 'describ':102,169 'determinist':366,406 'dialect':405 'differ':195 'dir':381,514,568 'direct':526 'directori':569 'discover':207 'distinct':191 'doesn':41 'dot':324 'doubl':545 'double-dash':544 'e.g':153,403 'effect':300 'enforc':86,635 'entir':160 'env':378 'environ':376 'err':128,139,475,477,480,575,578,581 'error':440,462,601,608,613 'even':37 'except':329 'exit':425,469 'explicit':43,418,649 'export':599 'express':394 'extend':294,343 'extern':293 'extract':457 'f.seek':129,140 'file':76,180,186,214,242,335,572 'filesystem':387 'first':265,291 'flag':494,500,503,508,525,536,555 'flag.parse':573 'flag.string':566 'flow':446 'fmt':277 'free':374,384 'func':460,472,563 'function':72,80,419,437 'generic':108,143 'get':312 'github.com':280 'github.com/foo/bar':279 'global':638,654 'go':2,7,18,28,48,67,79,91,121,275,471,553,588,607,625,642 'go-defens':641 'go-error-handl':606 'go-funct':78 'go-lint':90,624 'go-nam':66,587 'go-packag':1 'godoc':201 'goimport':267,630 'good':122,554 'group':193,255,289,344,637 'grow':33 'guidanc':288 'handl':602,609 'helper':112 'hook':402 'i/o':386 'identifi':61 'implement':485 'import':10,51,87,119,250,251,276,309,316,317,325,326,341,352,621,636 'improv':206 'independ':368 'individu':60 'init':354,356,371,416,423,647 'initi':650 'io.seekstart':131 'keep':528 'librari':261,517,562 'like':110 'line':259,499 'lint':92,622,626 'linter':84 'local':308,632 'local-prefix':631 'log.fatal':431,479,580 'logic':458 'long':216 'main':320,427,434,465,473,507,557,564 'manag':11,272 'mean':116,136 'meaning':123 'must':362 'mutabl':653 'mylib.generate':576 'name':59,68,100,109,125,134,144,152,162,495,509,585,589,594,598 'need':413 'network':388 'never':181,327 'new':27 'nil':478,579 'non':443 'non-obvi':442 'obscur':115,135 'obvious':444 'one':173 'order':372 'organ':9,47,71,95,241,253,340 'os':278 'os.exit':429 'output':513,567,571 'outputdir':516,565,577 'overwhelm':203 'packag':3,8,21,36,46,49,64,94,98,99,105,124,161,163,190,222,240,245,262,311,321,347,506,537,584,593,604,615 'page':202 'paramet':522,560 'part':149,196 'pass':558 'pattern':456,488 'pb':313 'pflag':539 'pkg.go.dev':269 'pkg.go.dev/golang.org/x/tools/cmd/goimports)':268 'pluggabl':401 'point':470 'posix':542 'possibl':358 'practic':452 'precomput':407 'prefer':533 'prefix':633 'program':249 'project':29 'proto':297,310,346 'provid':106 'purpos':171 'question':165 'quick':285 'read':230,336,408,481,524 'refactor':415 'references/imports.md':337,338 'references/package-size.md':231,232,409,410,482,483 'relat':582 'renam':301,305,345 'replac':646 'requir':552 'respons':178 'return':439 'reusabl':532 'rsc.io':283 'rsc.io/goversion/version':282 'rule':88,286,287 'run':455,461,476,487 'see':65,77,89,586,605,623,640 'sentenc':174 'separ':189,256 'share':182 'shortcut':550 'side':299 'side-effect':298 'singl':75,220,399,468,548 'single-char':547 'single-typ':219 'size':164 'skill':54,583 'skill-go-packages' 'skip':450 'snake':511 'source-cxuu' 'spannertest.newdatabasefromfile':127 'split':31,176,197,204,210,237 'standard':260,535 'start':25 'state':377,639 'statement':449 'stdlib':290,295 'stringutil':154 'structur':17,247,489 'stutter':596 'subcommand':491 'suffix':314 'symbol':184,600 'system':389 'test':323,334 'test.newdatabasefromfile':138 'testabl':530 'topic-agent-skills' 'topic-ai-agent' 'topic-ai-assistant' 'topic-claude' 'topic-claude-code' 'topic-codex' 'topic-cursor' 'topic-golang' 'topic-llm' 'type':221 'unavoid':360 'understand':421 'unexport':183 'unless':303 'untest':447 'use':4,23,147,194,266,328,392,424,453,510,538 'user':40,192,199 'util':97,111 'v':620 'vagu':133 'var':379 'vs':619 'w':618 'whether':235 'within':62,73,243 'work':380 'would':226 'wrap':612","prices":[{"id":"3ad58fcd-fd2f-47b1-ac6b-fe50b6baa755","listingId":"d3200cec-bce7-480d-b239-015c018e5049","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"cxuu","category":"golang-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T22:13:19.629Z"}],"sources":[{"listingId":"d3200cec-bce7-480d-b239-015c018e5049","source":"github","sourceId":"cxuu/golang-skills/go-packages","sourceUrl":"https://github.com/cxuu/golang-skills/tree/main/skills/go-packages","isPrimary":false,"firstSeenAt":"2026-04-18T22:13:19.629Z","lastSeenAt":"2026-05-02T12:55:18.928Z"}],"details":{"listingId":"d3200cec-bce7-480d-b239-015c018e5049","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"cxuu","slug":"go-packages","github":{"repo":"cxuu/golang-skills","stars":82,"topics":["agent-skills","ai-agent","ai-assistant","claude","claude-code","codex","cursor","go","golang","llm"],"license":"apache-2.0","html_url":"https://github.com/cxuu/golang-skills","pushed_at":"2026-03-15T19:32:10Z","description":"AI Agent Skills for idiomatic, production-ready Go code, distilled from Google, Uber, Community","skill_md_sha":"9809fc8f1a213675d2350ae627db6d3200da8985","skill_md_path":"skills/go-packages/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/cxuu/golang-skills/tree/main/skills/go-packages"},"layout":"multi","source":"github","category":"golang-skills","frontmatter":{"name":"go-packages","license":"Apache-2.0","description":"Use when creating Go packages, organizing imports, managing dependencies, or deciding how to structure Go code into packages. Also use when starting a new Go project or splitting a growing codebase into packages, even if the user doesn't explicitly ask about package organization. Does not cover naming individual identifiers (see go-naming)."},"skills_sh_url":"https://skills.sh/cxuu/golang-skills/go-packages"},"updatedAt":"2026-05-02T12:55:18.928Z"}}