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 `github.com/99designs/gqlgen` or `github.com/graph-gophers/graphql-go`. Skill: golang-graphql Owner: samber Summary: 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. Tags: latest:0.2.0 Version history: v0.2.0 | 2026-08-2
Rank
62
Safety
84
Downloads
1.0k
Updated
Oct 11, 2026
Version
0.2.0
Source
CLAWHUB
About
What it does, and when to use it.
Capability contract not published. No trust telemetry is available yet. 1K downloads reported by the source. Last updated 10/11/2026.
Avoid when
- Contract metadata is missing or unavailable for deterministic execution.
Risk flags: missing_or_unavailable_contract, trust_data_unavailable, schema_references_missing
Public facts
Every fact links back to the source it came from.
- Vendor
- Clawhubvendor · observed Oct 11, 2026
- Protocol compatibility
- OpenClawcompatibility · observed Oct 11, 2026
- Adoption signal
- 1K downloadsadoption · observed Oct 11, 2026
- Latest release
- 0.2.0release · observed Aug 21, 2026
- Handshake status
- UNKNOWNsecurity
Install and run
Setup complexity: low.
clawhub skill install s173arkhs3131fq5jf769qq75583hdgt:golang-graphql- Setup complexity is LOW. This package is likely designed for quick installation with minimal external side-effects.
- Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data.
Contract: missing
curl -s "https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-graphql/snapshot"
Run-check
$0.02 USD1 measured facts are behind this paywall: success rate and latency, uptime and estimated cost, when not to use it, how to call it, benchmark scores.
Agents pay $0.02 in USDC. A card payment is $0.50, the smallest a card allows.
Documentation
CLAWHUB
140,742 characters of source documentation, loaded on request.
Extracted files
5 files captured from the source.
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.0"
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`) — prefer it 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 g_meta.json
{
"ownerId": "kn72rhnkwjfeex9wr1n7y24qa983cjn3",
"slug": "golang-graphql",
"version": "0.2.0",
"publishedAt": 1787318461360
}references/gqlgen.md
# gqlgen Reference
gqlgen is a schema-first, code-generation library. Write SDL, run `go generate`, fill in resolver bodies.
## Project Setup
```bash
# Bootstrap a new project
go run github.com/99designs/gqlgen init
# Pin the tool in go.mod for reproducible generation (Go 1.24+)
go get -tool github.com/99designs/gqlgen@latest
```
For Go <1.24 modules, use the legacy `tools.go` blank-import workaround instead.
```bash
# Regenerate after every schema change
go tool gqlgen generate
```
Never hand-edit generated files (`generated.go`, `models_gen.go`) — `generate` overwrites them.
## gqlgen.yml
```yaml
schema:
- graph/schema/*.graphql
exec:
filename: graph/generated.go
package: graph
model:
filename: graph/model/models_gen.go
package: model
resolver:
layout: follow-schema # one resolvers file per schema file
dir: graph
package: graph
filename_template: "{name}.resolvers.go"
autobind:
- github.com/me/app/internal/domain # reuse existing structs
models:
# ID: graphql.IntID # legacy only — use opaque string IDs for new schemas
User:
model: github.com/me/app/internal/domain.User
fields:
posts:
resolver: true # force a custom resolver (required for DataLoader fields)
omit_slice_element_pointers: true
struct_fields_always_pointers: false
resolvers_always_return_pointers: true
```
Key knobs:
- `autobind` — maps Go structs to GraphQL types; fields must match by name (case-insensitive)
- `models.<T>.model` — override which Go type backs a GraphQL type
- `fields.<f>.resolver: true` — force a custom resolver instead of struct field access; required for any field that should batch via DataLoader
- `struct_fields_always_pointers` / `resolvers_always_return_pointers` — controls `*T` vs `T` in generated signatures; match your domain model conventions
## Resolver Structure
The generated `Config` holds a `Resolvers` field of the generated interface. You implement it:
```go
// graph/resolver.go — you own this file, not generated
type Resolver struct {
db *sql.DB
userService *service.UserService
loaders *dataloaders.Loaders // injected per-request
}
```
Per-type resolvers implement the generated interface split by GraphQL type:
```go
type queryResolver struct{ *Resolver }
type mutationResolver struct{ *Resolver }
type userResolver struct{ *Resolver }
func (r *queryResolver) User(ctx context.Context, id string) (*model.User, error) { ... }
func (r *userResolver) Posts(ctx context.Context, obj *model.User) ([]*model.Post, error) { ... }
```
`obj` is the parent object — the entry point for walking the graph.
## DataLoaders (gqlgen)
Use `github.com/vikstrous/dataloadgen` (generics, fast) or `github.com/graph-gophers/dataloader`:
```go
// Inject per-request via middleware
func Middleware(db *sql.DB, next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
loaders := &Loaders{
PostsByUserID: dataloadgen.Newreferences/graphql-go.md
# graph-gophers/graphql-go Reference
Schema-first, reflection-based — no codegen. Write SDL, bind Go resolver structs. Parse-time validation gives a fail-fast contract.
## Setup
```go
import (
"github.com/graph-gophers/graphql-go"
"github.com/graph-gophers/graphql-go/relay"
"github.com/graph-gophers/graphql-go/trace/otel"
)
schema := graphql.MustParseSchema(sdlString, &RootResolver{},
graphql.MaxDepth(10),
graphql.MaxParallelism(10),
graphql.UseFieldResolvers(), // expose exported struct fields without explicit methods
graphql.Tracer(otel.DefaultTracer()),
)
http.Handle("/graphql", &relay.Handler{Schema: schema})
```
`MustParseSchema` panics on invalid SDL or resolver mismatch — catch it at startup, not at request time.
## Resolver Structure
One exported method per schema field; name match is case-insensitive:
```go
type RootResolver struct {
db *sql.DB
}
type QueryResolver struct {
db *sql.DB
}
func (r *RootResolver) Query() *QueryResolver { return &QueryResolver{db: r.db} }
// Args struct for field arguments
func (r *QueryResolver) User(ctx context.Context, args struct{ ID graphql.ID }) (*UserResolver, error) {
user, err := r.db.GetUser(ctx, string(args.ID))
if err != nil {
return nil, err
}
return &UserResolver{user: user}, nil
}
```
Return resolver wrapper structs, not domain models directly — keeps GraphQL projection separate from persistence.
## Type Mapping
<!-- prettier-ignore -->
|GraphQL type|Go type|Notes|
|---|---|---|
|`ID`|`graphql.ID`|string alias|
|`Int`|`int32`|**NOT `int`** — mismatch is a parse-time error|
|`Float`|`float64`||
|`String`|`string`||
|`Boolean`|`bool`||
|`[T]`|`[]*T` or `[]T`||
|Nullable `T`|`*T`|pointer = nullable|
|Non-null `T!`|`T`|non-pointer|
|Custom scalar|implement `UnmarshalGraphQL(input any) error` + `MarshalJSON() ([]byte, error)`||
|Enum|typed string alias||
|Input|exported struct with field tags optional||
|Interface/Union|Go interface returned; `ToConcreteType() (*T, bool)` discriminators||
Common mistake: using `int` for an `Int!` field — the parser rejects it with a type mismatch error.
## Nullable vs Non-null Arguments
```go
// ✓ Good — pointer arg = nullable in schema
func (r *QueryResolver) Users(ctx context.Context, args struct {
Role *string // nullable: Role in SDL
Limit int32 // non-null: Limit! in SDL
}) ([]*UserResolver, error) { ... }
```
Forgetting `*` on a nullable argument causes unmarshal failure when clients send `null`.
## Custom Scalar
```go
type DateTime struct{ time.Time }
func (d *DateTime) UnmarshalGraphQL(input any) error {
s, ok := input.(string)
if !ok {
return fmt.Errorf("DateTime must be a string")
}
t, err := time.Parse(time.RFC3339, s)
if err != nil {
return err
}
d.Time = t
return nil
}
func (d DateTime) MarshalJSON() ([]byte, error) {
return json.Marshal(d.Time.Format(time.RFC3339))
}
```
## Interfaces and Unions
```graphql
inreferences/testing.md
# Testing GraphQL in Go
## gqlgen — Client Harness
The `github.com/99designs/gqlgen/client` package drives the full stack (directives, middleware, resolvers) via an `http.Handler`:
```go
func TestCreateUser(t *testing.T) {
// Build the full handler with real dependencies (use a test DB)
srv := handler.NewDefaultServer(graph.NewExecutableSchema(graph.Config{
Resolvers: &graph.Resolver{
DB: testDB,
},
}))
c := client.New(srv)
var resp struct {
CreateUser struct {
User struct {
ID string
Email string
}
Errors []struct{ Message string }
}
}
c.MustPost(`
mutation CreateUser($email: String!, $name: String!) {
createUser(input: {email: $email, name: $name}) {
user { id email }
errors { message }
}
}
`, &resp,
client.Var("email", "[email protected]"),
client.Var("name", "Alice"),
client.AddHeader("Authorization", "Bearer test-token"),
)
require.Empty(t, resp.CreateUser.Errors)
require.Equal(t, "[email protected]", resp.CreateUser.User.Email)
}
```
For unit testing individual resolvers, call resolver methods directly with a constructed `Resolver` and a real `context.Context` — no HTTP overhead.
## gqlgen — Testing with DataLoaders
Wrap the test server with the DataLoader middleware so resolver tests exercise the full batching path:
```go
srv := handler.NewDefaultServer(es)
h := dataloaders.Middleware(testDB, srv)
c := client.New(h)
```
## gqlgen — Testing Subscriptions
Use `client.Subscription` to test subscription resolvers:
```go
sub := c.Subscription(`subscription { messageAdded(room: "general") { content } }`)
defer sub.Close()
// Trigger an event
publishMessage("general", "hello")
var event struct{ MessageAdded struct{ Content string } }
err := sub.Next(&event)
require.NoError(t, err)
require.Equal(t, "hello", event.MessageAdded.Content)
```
## graph-gophers — gqltesting
```go
func TestUser(t *testing.T) {
gqltesting.RunTests(t, []*gqltesting.Test{
{
Schema: schema,
Query: `{ user(id: "1") { name email } }`,
ExpectedResult: `{"user":{"name":"Alice","email":"[email protected]"}}`,
},
{
Schema: schema,
Query: `{ user(id: "999") { name } }`,
ExpectedErrors: []*gqlerrors.QueryError{
{Message: "user not found", Extensions: map[string]any{"code": "NOT_FOUND"}},
},
},
})
}
```
For HTTP-level tests:
```go
func TestRelayHandler(t *testing.T) {
body := `{"query":"{ user(id: \"1\") { name } }"}`
req := httptest.NewRequest(http.MethodPost, "/graphql", strings.NewReader(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
relay.Handler{Schema: schema}.ServeHTTP(w, req)
require.EqualAionUi
Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!
activepieces
AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents
cherry-studio
AI productivity studio with smart chat, autonomous agents, and 300+ assistants.
CopilotKit
The Frontend for Agents & Generative UI. React + Angular
Machine-readable data
The same record, as JSON, for agents and crawlers.
{
"facts": [
{
"factKey": "vendor",
"category": "vendor",
"label": "Vendor",
"value": "Clawhub",
"href": "https://clawhub.ai/samber/skills/golang-graphql",
"sourceUrl": "https://clawhub.ai/samber/skills/golang-graphql",
"sourceType": "profile",
"confidence": "medium",
"observedAt": "2026-10-11T15:03:48.149Z",
"isPublic": true
},
{
"factKey": "protocols",
"category": "compatibility",
"label": "Protocol compatibility",
"value": "OpenClaw",
"href": "https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-graphql/contract",
"sourceUrl": "https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-graphql/contract",
"sourceType": "contract",
"confidence": "medium",
"observedAt": "2026-10-11T15:03:48.149Z",
"isPublic": true
},
{
"factKey": "traction",
"category": "adoption",
"label": "Adoption signal",
"value": "1K downloads",
"href": "https://clawhub.ai/samber/golang-graphql",
"sourceUrl": "https://clawhub.ai/samber/golang-graphql",
"sourceType": "profile",
"confidence": "medium",
"observedAt": "2026-10-11T15:03:48.149Z",
"isPublic": true
},
{
"factKey": "latest_release",
"category": "release",
"label": "Latest release",
"value": "0.2.0",
"href": "https://clawhub.ai/samber/golang-graphql",
"sourceUrl": "https://clawhub.ai/samber/golang-graphql",
"sourceType": "release",
"confidence": "medium",
"observedAt": "2026-08-21T13:21:01.360Z",
"isPublic": true
},
{
"factKey": "handshake_status",
"category": "security",
"label": "Handshake status",
"value": "UNKNOWN",
"href": "https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-graphql/trust",
"sourceUrl": "https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-graphql/trust",
"sourceType": "trust",
"confidence": "medium",
"observedAt": null,
"isPublic": true
}
],
"events": [
{
"eventType": "release",
"title": "Release 0.2.0",
"description": "golang-graphql v0.2.0 - Added support for additional agent tools: Bash(godig:*), Bash(gopls:*), LSP, mcp__gopls__*. - Declared path restrictions: skill now applies only to Go source files (`**/*.go`). - Updated compatibility statement to mention Codex and harnesses, not just Claude Code. - Integrated references to `godig` and `gopls` skills for better Go package discovery and navigation. - Removed the obsolete `skill-card.md` file.",
"href": "https://clawhub.ai/samber/golang-graphql",
"sourceUrl": "https://clawhub.ai/samber/golang-graphql",
"sourceType": "release",
"confidence": "medium",
"observedAt": "2026-08-21T13:21:01.360Z",
"isPublic": true
}
]
}Record generated Oct 11, 2026.
