mcpField
G
go

go

github.com/dralgorhythmDevelopment13355 installsUpdated 15w ago
Repository

About go

A Go development skill for developers, covering project organization, errors, concurrency, HTTP handlers, tests, and common tooling.

Key features

  1. 01Project structure guidance
  2. 02Custom error handling
  3. 03Concurrent work with errgroup
  4. 04HTTP handler patterns
  5. 05Testing and tooling guidance

Use cases

  1. 01Organizing a Go service repository
  2. 02Handling errors in application code
  3. 03Fetching multiple URLs concurrently
  4. 04Writing HTTP handlers and tests

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/dralgorhythm/claude-agentic-framework --skill go

After installing, type/goin Claude Code to confirm it loaded.

Details

From the project README

Go Development

Project Structure

myproject/
├── cmd/
│   └── server/
│       └── main.go
├── internal/
│   ├── handler/
│   ├── service/
│   └── repository/
├── pkg/
│   └── shared/
├── go.mod
└── go.sum

Error Handling

// Custom error types
type NotFoundError struct {
    Resource string
    ID       string
}

func (e *NotFoundError) Error() string {
    return fmt.Sprintf("%s not found: %s", e.Resource, e.ID)
}

// Error wrapping
func GetUser(id string) (*User, error) {
    user, err := db.FindUser(id)
    if err != nil {
        return nil, fmt.Errorf("GetUser(%s): %w", id, err)
    }
    return user, nil
}

// Error checking
if errors.Is(err, sql.ErrNoRows) {
    return nil, &NotFoundError{Resource: "user", ID: id}
}

Concurrency

// Goroutines with errgroup
func fetchAll(ctx context.Context, urls []string) ([]Response, error) {
    g, ctx := errgroup.WithContext(ctx)
    results := make([]Response, len(urls))

    for i, url := range urls {
        i, url := i, url // capture loop variables
        g.Go(func() error {
            resp, err := fetch(ctx, url)
            if err != nil {
                return err
            }
            results[i] = resp
            return nil
        })
    }

    if err := g.Wait(); err != nil {
        return nil, err
    }
    return results, nil
}

// Channels
func producer(ch chan<- int) {
    for i := 0; i < 10; i++ {
        ch <- i
    }
    close(ch)
}

func consumer(ch <-chan int) {
    for v := range ch {
        fmt.Println(v)
    }
}

HTTP Handler

func (h *Handler) GetUser(w http.ResponseWriter, r *http.Request) {
    ctx := r.Context()
    id := chi.URLParam(r, "id")

    user, err := h.service.GetUser(ctx, id)
    if err != nil {
        var notFound *NotFoundError
        if errors.As(err, &notFound) {
            http.Error(w, err.Error(), http.StatusNotFound)
            return
        }
        http.Error(w, "Internal error", http.StatusInternalServerError)
        return
    }

    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(user)
}

Testing

func TestGetUser(t *testing.T) {
    t.Parallel()

    tests := []struct {
        name    string
        id      string
        want    *User
        wantErr bool
    }{
        {
            name: "existing user",
            id:   "123",
            want: &User{ID: "123", Email: "[email protected]"},
        },
        {
            name:    "non-existent user",
            id:      "999",
            wantErr: true,
        },
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got, err := service.GetUser(context.Background(), tt.id)
            if (err != nil) != tt.wantErr {
                t.Errorf("error = %v, wantErr %v", err, tt.wantErr)
            }
            if !reflect.DeepEqual(got, tt.want) {
                t.Errorf("got = %v, want %v", got, tt.want)
            }
        })
    }
}

Tooling

# Format
gofmt -w .
goimports -w .

# Lint
golangci-lint run

# Test
go test -v -race -cover ./...

Comments

Markdown supported