agentsclimarketplace

Go packages

Skill muratmirgun/gophers/skills/go-packages

26 production-grade Go skills for Claude Code, Gemini CLI, and opencode.

Install
npx -y skills add muratmirgun/gophers --skill go-packages

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 8 stars8 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use when creating Go packages, organizing imports, managing dependencies, or structuring a Go project. Covers meaningful package names, package size, import grouping (stdlib first, then external), blank/dot imports, the run() pattern in main, init() restrictions, and CLI flag conventions. Apply proactively when starting a new module or splitting a growing codebase, even if the user did not explicitly ask about package layout. Does not cover identifier naming inside packages (see go-naming).

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

6.5 KB, as published. Nobody here has run it

Go Packages and Imports

A package is a unit of meaning, not a folder of files. Name it for what it provides, keep imports tidy, and put startup logic where it belongs.

Core Rules

  1. Package names describe what the package provides. util, helper, common, misc are not names.
  2. Imports are grouped: stdlib first, then external. goimports will keep this honest.
  3. Avoid init() — and when unavoidable, keep it deterministic and I/O-free.
  4. os.Exit / log.Fatal only inside main. Library code returns errors.
  5. Use the run() pattern so main has a single exit point and deferred cleanup runs.
  6. CLI flags belong in package main. Libraries take configuration as parameters.
  7. Blank imports belong in main or tests. Dot imports are essentially never appropriate.

Decision: How to Split a Package

QuestionIf "yes"
Can you state the package's purpose in one sentence?Probably right-sized
Do its files never share unexported symbols?Likely two packages glued by directory
Do distinct caller groups touch distinct files?Split along caller boundaries
Is the godoc index so long callers cannot find things?Split for discoverability
Does splitting create import cycles?Don't split

Read references/package-layout.md when deciding how to split a growing package, organizing cmd/, internal/, or designing a library API surface.

Naming Packages

// Good — meaningful
db := spannertest.NewDatabaseFromFile(...)
_, err := f.Seek(0, io.SeekStart)

// Bad — vague
db := test.NewDatabaseFromFile(...)
_, err := f.Seek(0, common.SeekStart)

Generic words may appear as part of a name (stringutil, iotest) but not as the whole name. Match the package to a concept the caller already knows.

Imports

import (
    "fmt"
    "os"

    "github.com/foo/bar"
    "rsc.io/goversion/version"
)
RuleGuidance
Group orderstdlib, then external; extended order may also separate protos and side-effect imports
RenamingAvoid unless there is a collision; rename the more-local import
Blank import (import _)Only main and tests
Dot import (import .)Effectively never; rare in test files for circular deps

Read references/imports-and-main.md for extended import grouping, proto pb suffixes, the run() pattern, and CLI flag conventions.

Avoid init()

When you must use init(), make it:

  1. Deterministic — same result every run.
  2. Independent of the order of other init()s.
  3. Free of environment state (env vars, working dir, args).
  4. Free of I/O (filesystem, network, syscalls).

Acceptable uses:

  • Precomputing a constant that cannot fit in a single expression.
  • Registering pluggable hooks (database/sql drivers).

If your init reads a file or calls a network API, refactor it into an explicit Setup() the caller invokes.

Exit Only in main

func main() {
    if err := run(); err != nil {
        log.Fatal(err)
    }
}

func run() error {
    // all the real work
    return nil
}

Why:

  • log.Fatal and os.Exit skip defer. Anywhere except main, that means leaked files, half-flushed buffers, undeleted temp dirs.
  • The run() pattern gives you one place to log a clean error and one place to set the exit code.

CLI Flags

  • Define flags in package main.
  • Flag names use snake_case: --output_dir, not --outputDir.
  • Libraries accept configuration through function parameters, never reach for flag.Lookup.
func main() {
    outputDir := flag.String("output_dir", ".", "directory for output files")
    flag.Parse()
    if err := mylib.Generate(*outputDir); err != nil {
        log.Fatal(err)
    }
}

Read references/init-and-globals.md for the boundaries between safe init-time computation, mutable globals, and dependency injection.

Anti-Patterns

Anti-patternWhy it hurtsDo this instead
package utilMeaningless name; import conflictsName after the concept
One huge package with 50 filesHard to navigate, slow buildsSplit by responsibility
init() reads config from diskSide effect at import timeExplicit Setup() in main
log.Fatal in library codeSkips defers, untestableReturn an error
os.Exit in a request handlerSame — plus crashes the serverReturn an error to the framework
import _ "pkg" in a librarySide effects on every importerRegister explicitly
import . "pkg" to "save typing"Tools lose track of where names come fromUse the package qualifier
Library reads a flag at import timeUntestable, non-reusableAccept config as parameter

Verification Checklist

  • Package name is concrete and unambiguous
  • Imports are grouped (stdlib first), goimports clean
  • No init() performs I/O or depends on env state
  • main is a single if err := run(); err != nil { log.Fatal(err) }
  • No os.Exit / log.Fatal* outside main
  • Flags are defined only in package main
  • No import . and no blank import outside main/tests
  • Package's purpose fits in one sentence

References

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.