go
46 lines · 1 tab
Leah Thompson
Jan 2026
1 tab
package service
import (
"context"
"golang.org/x/sync/errgroup"
)
type User struct{ ID string }
type Billing struct{ Plan string }
type Features struct{ Flags []string }
type Clients interface {
FetchUser(ctx context.Context, id string) (User, error)
FetchBilling(ctx context.Context, id string) (Billing, error)
FetchFeatures(ctx context.Context, id string) (Features, error)
}
func Aggregate(ctx context.Context, c Clients, id string) (User, Billing, Features, error) {
g, ctx := errgroup.WithContext(ctx)
var u User
var b Billing
var f Features
g.Go(func() error {
var err error
u, err = c.FetchUser(ctx, id)
return err
})
g.Go(func() error {
var err error
b, err = c.FetchBilling(ctx, id)
return err
})
g.Go(func() error {
var err error
f, err = c.FetchFeatures(ctx, id)
return err
})
if err := g.Wait(); err != nil {
return User{}, Billing{}, Features{}, err
}
return u, b, f, nil
}
1 file · go
Explain with highlit
When you need to call multiple downstream systems, errgroup is a great way to express “do these in parallel, cancel on first failure.” The key is using errgroup.WithContext, not a plain WaitGroup, so the group can propagate cancellation. Each goroutine should select on ctx.Done() (or pass ctx into the client) and return early when canceled, otherwise you get tail-latency even after the request has already failed. I also like keeping results in separate variables and only reading them after g.Wait() returns nil. This avoids subtle data races and keeps the error path obvious. It’s a compact pattern that scales well for aggregate endpoints.
Related snips
go
package api
import (
"net/http"
"runtime/debug"
)
Expose build metadata for debugging deploys
go
observability
build
by Leah Thompson
1 tab
go
package dbutil
import (
"context"
"github.com/jackc/pgconn"
Retry Postgres serialization failures with bounded attempts
go
postgres
transactions
by Leah Thompson
1 tab
rust
use crossbeam::channel::unbounded;
use std::thread;
fn main() {
let (tx, rx) = unbounded();
Crossbeam for advanced concurrent data structures
rust
concurrency
lock-free
by Marcus Chen
1 tab
javascript
// Creating a Promise
const myPromise = new Promise((resolve, reject) => {
const success = true;
setTimeout(() => {
if (success) {
Promises and async/await patterns for asynchronous JavaScript
javascript
promises
async-await
by Alex Chang
1 tab
rust
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
Channels (mpsc) for message passing between threads
rust
concurrency
channels
by Marcus Chen
1 tab
typescript
export type Settled<R> =
| { status: 'fulfilled'; value: R }
| { status: 'rejected'; reason: unknown };
export interface ConcurrencyOptions {
limit: number;
Simple concurrency limiter for batch operations
node
concurrency
async
by codesnips
2 tabs
Share this code
Here's the card — post it anywhere.