Skip to content
Development
Skill

/golang-graphql

Implements GraphQL APIs in Golang using gqlgen or graphql-go. Apply when building GraphQL servers, designing schemas, writing resolvers, handling subscriptions, or integrating GraphQL with existing Go HTTP services. Also apply when the codebase imports

From plugin
cc-skills-golang
3.3k46 skills
Install
$ npx -y skills add samber/cc-skills-golang --skill golang-graphql --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/golang-graphql

Context preview

The summary Claude sees to decide when to auto-load this skill.

Implements GraphQL APIs in Golang using gqlgen or graphql-go. Apply when building GraphQL servers, designing schemas, writing resolvers, handling subscriptions, or integrating GraphQL with existing Go HTTP services. Also apply when the codebase imports

SKILL.md

golang-graphql.SKILL.md
name: golang-graphql
description: "Implements GraphQL APIs in Golang using gqlgen or graphql-go. Apply when building GraphQL servers, designing schemas, writing resolvers, handling subscriptions, or integrating GraphQL with existing Go HTTP services. Also apply when the codebase imports `github.com/99designs/gqlgen` or `github.com/graph-gophers/graphql-go`."
user-invocable: false
license: MIT
compatibility: Designed for Claude Code, Codex or similar harness, and for projects using Golang.
metadata:
  author: samber
  version: "0.2.2"
  openclaw:
    emoji: "🔮"
    homepage: https://github.com/samber/cc-skills-golang
    requires:
      bins:
        - go
    install: []
    skill-library-version: "0.17.89"
allowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent WebFetch mcp__context7__resolve-library-id mcp__context7__query-docs Bash(curl:*) Bash(godig:*) Bash(gopls:*) LSP mcp__gopls__*
paths:
  - "**/*.go"

**Persona:** You are a Go GraphQL engineer. You design schemas deliberately, batch database access to prevent N+1, and treat query complexity limits as non-optional in production.

**Modes:**

  • **Build mode** — generating new schemas, resolvers, or server setup: follow the skill's sequential instructions; launch a background agent to grep for existing resolver patterns and naming conventions before generating new code.
  • **Review mode** — auditing a GraphQL codebase or PR: use a sub-agent to scan for N+1 resolver patterns, missing complexity caps, global DataLoaders, and introspection enabled in production, in parallel with reading the business logic.

> **Community default.** A company skill that explicitly supersedes `samber/cc-skills-golang@golang-graphql` skill takes precedence.

Go GraphQL Best Practices

Both major libraries are schema-first: write SDL (`.graphql` files), bind Go resolvers. Choose based on project size and team preferences.

This skill is not exhaustive — refer to each library's official documentation and code examples for current API signatures:

  • For Go package docs, symbols, versions, importers, and known vulnerabilities, → See `samber/cc-skills-golang@golang-pkg-go-dev` skill (`godig`), preferred over Context7 for Go package facts.
  • To navigate this library's usage in your own code (definitions, call sites, diagnostics), → See `samber/cc-skills-golang@golang-gopls` skill (`gopls`).
  • Context7 remains a fallback for docs not indexed on pkg.go.dev.

Library Choice

| Library | Approach | Type safety | Build step | Best for | | --- | --- | --- | --- | --- | | `github.com/99designs/gqlgen` | Codegen | Compile-time | `go generate` | Large schemas, federation, strict types | | `github.com/graph-gophers/graphql-go` | Reflection | Parse-time | None | Simple schemas, fast iteration | | `github.com/graphql-go/graphql` | Code-first | Runtime | None | **Avoid** — verbose, no SDL |

Pick **gqlgen** when: Apollo Federation is required, schema is large (100+ types), or the team wants generated stubs and zero reflection overhead.

Pick **graph-gophers** when: schema is small/medium, the build pipeline should stay simple, or a dynamic schema is needed.

For deep-dive on each library, see [gqlgen reference](./references/gqlgen.md) and [graphql-go reference](./references/graphql-go.md).

Schema Design

# ✓ Good — explicit nullability; ID scalar for opaque identifiers
type User {
  id: ID!
  email: String! # non-null: the server can always return this
  bio: String # nullable: may be unset
  posts(first: Int = 10, after: String): PostConnection!
}

# ✗ Bad — Int ID leaks implementation details, breaks client caching
type Post {
  id: Int!
}

**Nullability rule:** mark a field `!` only when the server can _always_ return a value. A resolver error on a non-null field nulls the parent object, causing cascade failures; nullable fields only null the field itself.

**Pagination:** use Relay cursor connections (`Connection`/`Edge`/`PageInfo`) for list fields. Avoid offset pagination on large datasets — cursors are stable under concurrent writes.

**Mutations:** wrap results in an envelope type so clients receive business errors alongside partial results without polluting the GraphQL `errors` array:

type CreateUserPayload {
  user: User
  errors: [UserError!]!
}

Resolver Patterns

Keep resolvers thin — they translate GraphQL inputs to domain calls and domain responses to GraphQL outputs.

// ✓ Good — resolver delegates to service layer
func (r *mutationResolver) CreateUser(ctx context.Context, input model.CreateUserInput) (*model.CreateUserPayload, error) {
    user, err := r.userService.Create(ctx, input.Email, input.Name)
    if err != nil {
        return nil, formatError(err)
    }
    return &model.CreateUserPayload{User: toGQLUser(user)}, nil
}

// ✗ Bad — SQL in resolver, no separation of concerns
func (r *queryResolver) User(ctx context.Context, id string) (*model.User, error) {
    row := r.db.QueryRowContext(ctx, "SELECT * FROM users WHERE id = $1", id)
    // ...
}

Use per-type resolver structs (`userResolver`, `postResolver`) rather than one monolithic resolver for all fields.

N+1 Prevention (DataLoaders)

Each `User.posts` resolver fires a SQL query per user without batching — O(n) DB calls for n users. DataLoaders solve this by coalescing per-field loads into a single batch query.

**Critical rule: DataLoaders MUST be created per-request in HTTP middleware, never globally.** A global DataLoader caches across requests — stale data, potential cross-user data leakage.

// ✓ Good — per-request DataLoader in middleware
func DataLoaderMiddleware(db *sql.DB, next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        loaders := &Loaders{
            PostsByUserID: newPostsByUserIDLoader(r.Context(), db),
        }
        ctx := context.WithValue(r.Context(), loadersKey, loaders)
        next.ServeHTTP(w, r.With
Read more
Ships withcc-skills-golang

AI agent skills are reusable instruction sets that extend your coding assistant with domain-specific expertise, loaded on demand so they don't bloat your context. This repository covers Go-specific skills only (language, testing, security, observability, etc.)

Get the whole plugin

Other skills on cc-skills-golang.