This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Examples

Learn by building real microservices with go-micro

Learn by Example

Runnable examples are the fastest way to move from reading the guides to changing one thing. Start with the path that matches where you are in the services → agents → workflows lifecycle.

Start here

For the provider-free first-agent route, run examples/first-agent, then follow No-secret First Agent, Your First Agent, Debugging your agent, and the 0→hero Reference.

GoalRunnable exampleWhy it is useful
0→1 serviceexamples/hello-worldSmallest RPC service with a client call and health checks.
Provider-free first agentexamples/first-agentSmallest service-backed agent with a deterministic mock model; no provider key required.
First service-backed agentexamples/agent-demoMulti-service project/task/team app with agent playground integration.
0→hero lifecycleexamples/supportNo-secret support-desk story: typed services, an agent, an event-driven flow, and a guardrail.
Planning and delegationexamples/agent-plan-delegateTwo agents collaborate through plan and delegate over normal Go Micro RPC.
Durable agent runsexamples/agent-durableCheckpoint and resume a model-directed run without replaying completed tool side effects.
Durable workflowsexamples/flow-durableOrdered, checkpointed flow steps resume without duplicating completed side effects.
AI-callable servicesexamples/mcpMCP examples that expose service endpoints as model tools.

Guide-to-example map

Repository examples

See the repository examples index for the complete runnable list, including deployment, auth, gRPC interop, MCP, agent, and flow examples.

More

1 - Learn by Example

A collection of small, focused examples demonstrating common patterns with Go Micro.

1.1 - Hello Service

A minimal HTTP service using Go Micro, with a single endpoint.

Service

package main

import (
    "context"
    "go-micro.dev/v6"
)

type Request struct { Name string `json:"name"` }

type Response struct { Message string `json:"message"` }

type Say struct{}

func (h *Say) Hello(ctx context.Context, req *Request, rsp *Response) error {
    rsp.Message = "Hello " + req.Name
    return nil
}

func main() {
    svc := micro.NewService("helloworld")
    svc.Init()
    svc.Handle(new(Say))
    svc.Run()
}

Run it:

go run main.go

Call it:

curl -XPOST \
  -H 'Content-Type: application/json' \
  -H 'Micro-Endpoint: Say.Hello' \
  -d '{"name": "Alice"}' \
  http://127.0.0.1:8080

Set a fixed address:

svc := micro.NewService("helloworld",
    micro.Address(":8080"),
)

1.2 - Rpc Client

Call a running service using the Go Micro client.
package main

import (
    "context"
    "fmt"
    "go-micro.dev/v6"
)

type Request struct { Name string }

type Response struct { Message string }

func main() {
    svc := micro.NewService("caller")
    svc.Init()

    req := svc.Client().NewRequest("helloworld", "Say.Hello", &Request{Name: "John"})
    var rsp Response

    if err := svc.Client().Call(context.TODO(), req, &rsp); err != nil {
        fmt.Println("error:", err)
        return
    }

    fmt.Println(rsp.Message)
}

1.3 - Service Discovery with Consul

Use Consul as the service registry.

In code

package main

import (
    "go-micro.dev/v6"
    "go-micro.dev/v6/registry/consul"
)

func main() {
    reg := consul.NewConsulRegistry()
    svc := micro.NewService("consul-registry", micro.Registry(reg))
    svc.Init()
    svc.Run()
}

Via environment

Run your service with env vars set:

MICRO_REGISTRY=consul MICRO_REGISTRY_ADDRESS=127.0.0.1:8500 go run main.go

1.4 - Store Postgres

Use the Postgres store for persistent key/value state.

In code

package main

import (
    "log"
    "go-micro.dev/v6"
    "go-micro.dev/v6/store"
    postgres "go-micro.dev/v6/store/postgres"
)

func main() {
    st := postgres.NewStore()
    svc := micro.NewService("postgres-store", micro.Store(st))
    svc.Init()

    _ = store.Write(&store.Record{Key: "foo", Value: []byte("bar")})
    recs, _ := store.Read("foo")
    log.Println("value:", string(recs[0].Value))

    svc.Run()
}

Via environment

Run your service with env vars set:

MICRO_STORE=postgres \
MICRO_STORE_ADDRESS=postgres://user:pass@127.0.0.1:5432/postgres \
MICRO_STORE_DATABASE=micro \
MICRO_STORE_TABLE=micro \
go run main.go

1.5 - Transport Nats

Use NATS as the transport between services.

In code

package main

import (
    "go-micro.dev/v6"
    tnats "go-micro.dev/v6/transport/nats"
)

func main() {
    t := tnats.NewTransport()
    svc := micro.NewService("nats-transport", micro.Transport(t))
    svc.Init()
    svc.Run()
}

Via environment

Run your service with env vars set:

MICRO_TRANSPORT=nats MICRO_TRANSPORT_ADDRESS=nats://127.0.0.1:4222 go run main.go

2 - Real-World Examples

Production-ready patterns and complete application examples.

Real-World Examples

Production-ready patterns and complete application examples.

Available Examples

Coming Soon

We’re actively working on additional real-world examples. Contributions are welcome!

Complete Applications

  • Event-Driven Microservices - Pub/sub patterns
  • CQRS Pattern - Command Query Responsibility Segregation
  • Saga Pattern - Distributed transactions

Production Patterns

  • Health Checks and Readiness
  • Retry and Circuit Breaking
  • Distributed Tracing with OpenTelemetry
  • Structured Logging
  • Metrics and Monitoring

Testing Strategies

  • Unit Testing Services
  • Integration Testing
  • Contract Testing
  • Load Testing

Deployment

  • Kubernetes Deployment
  • Docker Compose Setup
  • CI/CD Pipeline Examples
  • Blue-Green Deployment

Integration Examples

  • PostgreSQL with Transactions
  • Redis Caching Strategies
  • Message Queue Integration
  • External API Integration

Each example will include:

  • Complete, runnable code
  • Configuration for development and production
  • Testing approach
  • Common pitfalls and solutions

Want to contribute? See our Contributing Guide.

2.1 - API Gateway with Backend Services

A complete example showing an API gateway routing to multiple backend microservices.

Architecture

                  ┌─────────────┐
   Client ───────>│ API Gateway │
                  └──────┬──────┘
                         │
          ┌──────────────┼──────────────┐
          │              │              │
    ┌─────▼────┐   ┌────▼─────┐  ┌────▼─────┐
    │  Users   │   │  Orders  │  │ Products │
    │ Service  │   │ Service  │  │ Service  │
    └──────────┘   └──────────┘  └──────────┘
          │              │              │
          └──────────────┼──────────────┘
                         │
                  ┌──────▼──────┐
                  │  PostgreSQL │
                  └─────────────┘

Services

1. Users Service

// services/users/main.go
package main

import (
    "context"
    "database/sql"
    "go-micro.dev/v6"
    "go-micro.dev/v6/server"
    _ "github.com/lib/pq"
)

type User struct {
    ID    int64  `json:"id"`
    Email string `json:"email"`
    Name  string `json:"name"`
}

type UsersService struct {
    db *sql.DB
}

type GetUserRequest struct {
    ID int64 `json:"id"`
}

type GetUserResponse struct {
    User *User `json:"user"`
}

func (s *UsersService) Get(ctx context.Context, req *GetUserRequest, rsp *GetUserResponse) error {
    var u User
    err := s.db.QueryRow("SELECT id, email, name FROM users WHERE id = $1", req.ID).
        Scan(&u.ID, &u.Email, &u.Name)
    if err != nil {
        return err
    }
    rsp.User = &u
    return nil
}

func main() {
    db, err := sql.Open("postgres", "postgres://user:pass@localhost/users?sslmode=disable")
    if err != nil {
        panic(err)
    }
    defer db.Close()

    svc := micro.NewService("users",
        micro.Version("1.0.0"),
    )

    svc.Init()

    server.RegisterHandler(svc.Server(), &UsersService{db: db})

    if err := svc.Run(); err != nil {
        panic(err)
    }
}

2. Orders Service

// services/orders/main.go
package main

import (
    "context"
    "database/sql"
    "time"
    "go-micro.dev/v6"
    "go-micro.dev/v6/client"
    "go-micro.dev/v6/server"
)

type Order struct {
    ID        int64     `json:"id"`
    UserID    int64     `json:"user_id"`
    ProductID int64     `json:"product_id"`
    Amount    float64   `json:"amount"`
    Status    string    `json:"status"`
    CreatedAt time.Time `json:"created_at"`
}

type OrdersService struct {
    db     *sql.DB
    client client.Client
}

type CreateOrderRequest struct {
    UserID    int64   `json:"user_id"`
    ProductID int64   `json:"product_id"`
    Amount    float64 `json:"amount"`
}

type CreateOrderResponse struct {
    Order *Order `json:"order"`
}

func (s *OrdersService) Create(ctx context.Context, req *CreateOrderRequest, rsp *CreateOrderResponse) error {
    // Verify user exists
    userReq := s.client.NewRequest("users", "UsersService.Get", &struct{ ID int64 }{ID: req.UserID})
    userRsp := &struct{ User interface{} }{}
    if err := s.client.Call(ctx, userReq, userRsp); err != nil {
        return err
    }

    // Verify product exists
    prodReq := s.client.NewRequest("products", "ProductsService.Get", &struct{ ID int64 }{ID: req.ProductID})
    prodRsp := &struct{ Product interface{} }{}
    if err := s.client.Call(ctx, prodReq, prodRsp); err != nil {
        return err
    }

    // Create order
    var o Order
    err := s.db.QueryRow(`
        INSERT INTO orders (user_id, product_id, amount, status, created_at)
        VALUES ($1, $2, $3, $4, $5)
        RETURNING id, user_id, product_id, amount, status, created_at
    `, req.UserID, req.ProductID, req.Amount, "pending", time.Now()).
        Scan(&o.ID, &o.UserID, &o.ProductID, &o.Amount, &o.Status, &o.CreatedAt)

    if err != nil {
        return err
    }

    rsp.Order = &o
    return nil
}

func main() {
    db, err := sql.Open("postgres", "postgres://user:pass@localhost/orders?sslmode=disable")
    if err != nil {
        panic(err)
    }
    defer db.Close()

    svc := micro.NewService("orders",
        micro.Version("1.0.0"),
    )

    svc.Init()

    server.RegisterHandler(svc.Server(), &OrdersService{
        db:     db,
        client: svc.Client(),
    })

    if err := svc.Run(); err != nil {
        panic(err)
    }
}

3. API Gateway

// gateway/main.go
package main

import (
    "encoding/json"
    "net/http"
    "strconv"
    "go-micro.dev/v6"
    "go-micro.dev/v6/client"
)

type Gateway struct {
    client client.Client
}

func (g *Gateway) GetUser(w http.ResponseWriter, r *http.Request) {
    idStr := r.URL.Query().Get("id")
    id, err := strconv.ParseInt(idStr, 10, 64)
    if err != nil {
        http.Error(w, "invalid id", http.StatusBadRequest)
        return
    }

    req := g.client.NewRequest("users", "UsersService.Get", &struct{ ID int64 }{ID: id})
    rsp := &struct{ User interface{} }{}

    if err := g.client.Call(r.Context(), req, rsp); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

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

func (g *Gateway) CreateOrder(w http.ResponseWriter, r *http.Request) {
    var body struct {
        UserID    int64   `json:"user_id"`
        ProductID int64   `json:"product_id"`
        Amount    float64 `json:"amount"`
    }

    if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
        http.Error(w, "invalid request", http.StatusBadRequest)
        return
    }

    req := g.client.NewRequest("orders", "OrdersService.Create", body)
    rsp := &struct{ Order interface{} }{}

    if err := g.client.Call(r.Context(), req, rsp); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusCreated)
    json.NewEncoder(w).Encode(rsp)
}

func main() {
    svc := micro.NewService("api.gateway",
    )
    svc.Init()

    gw := &Gateway{client: svc.Client()}

    http.HandleFunc("/users", gw.GetUser)
    http.HandleFunc("/orders", gw.CreateOrder)

    http.ListenAndServe(":8080", nil)
}

Running the Example

Development (Local)

# Terminal 1: Users service
cd services/users
go run main.go

# Terminal 2: Products service
cd services/products
go run main.go

# Terminal 3: Orders service
cd services/orders
go run main.go

# Terminal 4: API Gateway
cd gateway
go run main.go

Testing

# Get user
curl http://localhost:8080/users?id=1

# Create order
curl -X POST http://localhost:8080/orders \
  -H 'Content-Type: application/json' \
  -d '{"user_id": 1, "product_id": 100, "amount": 99.99}'

Docker Compose

version: '3.8'

services:
  postgres:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: secret
    ports:
      - "5432:5432"

  users:
    build: ./services/users
    environment:
      MICRO_REGISTRY: nats
      MICRO_REGISTRY_ADDRESS: nats://nats:4222
      DATABASE_URL: postgres://postgres:secret@postgres/users
    depends_on:
      - postgres
      - nats

  products:
    build: ./services/products
    environment:
      MICRO_REGISTRY: nats
      MICRO_REGISTRY_ADDRESS: nats://nats:4222
      DATABASE_URL: postgres://postgres:secret@postgres/products
    depends_on:
      - postgres
      - nats

  orders:
    build: ./services/orders
    environment:
      MICRO_REGISTRY: nats
      MICRO_REGISTRY_ADDRESS: nats://nats:4222
      DATABASE_URL: postgres://postgres:secret@postgres/orders
    depends_on:
      - postgres
      - nats

  gateway:
    build: ./gateway
    ports:
      - "8080:8080"
    environment:
      MICRO_REGISTRY: nats
      MICRO_REGISTRY_ADDRESS: nats://nats:4222
    depends_on:
      - users
      - products
      - orders

  nats:
    image: nats:latest
    ports:
      - "4222:4222"

Run with:

docker-compose up

Key Patterns

  1. Service isolation: Each service owns its database
  2. Service communication: Via Go Micro client
  3. Gateway pattern: Single entry point for clients
  4. Error handling: Proper HTTP status codes
  5. Registry: mDNS for local, NATS for Docker

Production Considerations

  • Add authentication/authorization
  • Implement request tracing
  • Add circuit breakers for service calls
  • Use connection pooling
  • Add rate limiting
  • Implement proper logging
  • Use health checks
  • Add metrics collection

See Production Patterns for more details.

2.2 - Graceful Shutdown

Properly shutting down services to avoid dropped requests and data loss.

The Problem

Without graceful shutdown:

  • In-flight requests are dropped
  • Database connections leak
  • Resources aren’t cleaned up
  • Load balancers don’t know service is down

Solution

Go Micro handles SIGTERM/SIGINT by default, but you need to implement cleanup logic.

Basic Pattern

package main

import (
    "context"
    "os"
    "os/signal"
    "syscall"
    "time"
    "go-micro.dev/v6"
    "go-micro.dev/v6/logger"
)

func main() {
    svc := micro.NewService("myservice",
        micro.BeforeStop(func() error {
            logger.Info("Service stopping, running cleanup...")
            return cleanup()
        }),
    )

    svc.Init()

    // Your service logic
    if err := svc.Handle(new(Handler)); err != nil {
        logger.Fatal(err)
    }

    // Run with graceful shutdown
    if err := svc.Run(); err != nil {
        logger.Fatal(err)
    }

    logger.Info("Service stopped gracefully")
}

func cleanup() error {
    // Close database connections
    // Flush logs
    // Stop background workers
    // etc.
    return nil
}

Database Cleanup

type Service struct {
    db *sql.DB
}

func (s *Service) Shutdown(ctx context.Context) error {
    logger.Info("Closing database connections...")
    
    // Stop accepting new requests
    s.db.SetMaxOpenConns(0)
    
    // Wait for existing connections to finish (with timeout)
    done := make(chan struct{})
    go func() {
        s.db.Close()
        close(done)
    }()
    
    select {
    case <-done:
        logger.Info("Database closed gracefully")
        return nil
    case <-ctx.Done():
        logger.Warn("Database close timeout, forcing")
        return ctx.Err()
    }
}

Background Workers

type Worker struct {
    quit chan struct{}
    done chan struct{}
}

func (w *Worker) Start() {
    w.quit = make(chan struct{})
    w.done = make(chan struct{})
    
    go func() {
        defer close(w.done)
        ticker := time.NewTicker(5 * time.Second)
        defer ticker.Stop()
        
        for {
            select {
            case <-ticker.C:
                w.doWork()
            case <-w.quit:
                logger.Info("Worker stopping...")
                return
            }
        }
    }()
}

func (w *Worker) Stop(timeout time.Duration) error {
    close(w.quit)
    
    select {
    case <-w.done:
        logger.Info("Worker stopped gracefully")
        return nil
    case <-time.After(timeout):
        return fmt.Errorf("worker shutdown timeout")
    }
}

Complete Example

package main

import (
    "context"
    "database/sql"
    "fmt"
    "os"
    "os/signal"
    "sync"
    "syscall"
    "time"
    
    "go-micro.dev/v6"
    "go-micro.dev/v6/logger"
)

type Application struct {
    db      *sql.DB
    workers []*Worker
    wg      sync.WaitGroup
    mu      sync.RWMutex
    closing bool
}

func NewApplication(db *sql.DB) *Application {
    return &Application{
        db:      db,
        workers: make([]*Worker, 0),
    }
}

func (app *Application) AddWorker(w *Worker) {
    app.workers = append(app.workers, w)
    w.Start()
}

func (app *Application) Shutdown(ctx context.Context) error {
    app.mu.Lock()
    if app.closing {
        app.mu.Unlock()
        return nil
    }
    app.closing = true
    app.mu.Unlock()
    
    logger.Info("Starting graceful shutdown...")
    
    // Stop accepting new work
    logger.Info("Stopping workers...")
    for _, w := range app.workers {
        if err := w.Stop(5 * time.Second); err != nil {
            logger.Warnf("Worker failed to stop: %v", err)
        }
    }
    
    // Wait for in-flight requests (with timeout)
    shutdownComplete := make(chan struct{})
    go func() {
        app.wg.Wait()
        close(shutdownComplete)
    }()
    
    select {
    case <-shutdownComplete:
        logger.Info("All requests completed")
    case <-ctx.Done():
        logger.Warn("Shutdown timeout, forcing...")
    }
    
    // Close resources
    logger.Info("Closing database...")
    if err := app.db.Close(); err != nil {
        logger.Errorf("Database close error: %v", err)
    }
    
    logger.Info("Shutdown complete")
    return nil
}

func main() {
    db, err := sql.Open("postgres", os.Getenv("DATABASE_URL"))
    if err != nil {
        logger.Fatal(err)
    }
    
    app := NewApplication(db)
    
    // Add background workers
    app.AddWorker(&Worker{name: "cleanup"})
    app.AddWorker(&Worker{name: "metrics"})
    
    svc := micro.NewService("myservice",
        micro.BeforeStop(func() error {
            ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
            defer cancel()
            return app.Shutdown(ctx)
        }),
    )
    
    svc.Init()
    
    handler := &Handler{app: app}
    if err := svc.Handle(handler); err != nil {
        logger.Fatal(err)
    }
    
    // Run service
    if err := svc.Run(); err != nil {
        logger.Fatal(err)
    }
}

Kubernetes Integration

Liveness and Readiness Probes

func (h *Handler) Health(ctx context.Context, req *struct{}, rsp *HealthResponse) error {
    // Liveness: is the service alive?
    rsp.Status = "ok"
    return nil
}

func (h *Handler) Ready(ctx context.Context, req *struct{}, rsp *ReadyResponse) error {
    h.app.mu.RLock()
    closing := h.app.closing
    h.app.mu.RUnlock()
    
    if closing {
        // Stop receiving traffic during shutdown
        return fmt.Errorf("shutting down")
    }
    
    // Check dependencies
    if err := h.app.db.Ping(); err != nil {
        return fmt.Errorf("database unhealthy: %w", err)
    }
    
    rsp.Status = "ready"
    return nil
}

Kubernetes Manifest

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myservice
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: myservice
        image: myservice:latest
        ports:
        - containerPort: 8080
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
        lifecycle:
          preStop:
            exec:
              # Give service time to drain before SIGTERM
              command: ["/bin/sh", "-c", "sleep 10"]
      terminationGracePeriodSeconds: 40

Best Practices

  1. Set timeouts: Don’t wait forever for shutdown
  2. Stop accepting work early: Set readiness to false
  3. Drain in-flight requests: Let current work finish
  4. Close resources properly: Databases, file handles, etc.
  5. Log shutdown progress: Help debugging
  6. Handle SIGTERM and SIGINT: Kubernetes sends SIGTERM
  7. Coordinate with load balancer: Use readiness probes
  8. Test shutdown: Regularly test graceful shutdown works

Testing Shutdown

# Start service
go run main.go &
PID=$!

# Send some requests
for i in {1..10}; do
    curl http://localhost:8080/endpoint &
done

# Trigger graceful shutdown
kill -TERM $PID

# Verify all requests completed
wait

Common Pitfalls

  • No timeout: Service hangs during shutdown
  • Not stopping workers: Background jobs continue
  • Database leaks: Connections not closed
  • Ignored signals: Service killed forcefully
  • No readiness probe: Traffic during shutdown

3 - Hello Service

A minimal HTTP service using Go Micro, with a single endpoint.

Service

package main

import (
    "context"
    "go-micro.dev/v6"
)

type Request struct { Name string `json:"name"` }

type Response struct { Message string `json:"message"` }

type Say struct{}

func (h *Say) Hello(ctx context.Context, req *Request, rsp *Response) error {
    rsp.Message = "Hello " + req.Name
    return nil
}

func main() {
    svc := micro.NewService("helloworld")
    svc.Init()
    svc.Handle(new(Say))
    svc.Run()
}

Run it:

go run main.go

Call it:

curl -XPOST \
  -H 'Content-Type: application/json' \
  -H 'Micro-Endpoint: Say.Hello' \
  -d '{"name": "Alice"}' \
  http://127.0.0.1:8080

Set a fixed address:

svc := micro.NewService("helloworld",
    micro.Address(":8080"),
)

4 - NATS Transport

Use NATS as the transport between services.

In code

package main

import (
    "go-micro.dev/v6"
    tnats "go-micro.dev/v6/transport/nats"
)

func main() {
    t := tnats.NewTransport()
    svc := micro.NewService("nats-transport", micro.Transport(t))
    svc.Init()
    svc.Run()
}

Via environment

Run your service with env vars set:

MICRO_TRANSPORT=nats MICRO_TRANSPORT_ADDRESS=nats://127.0.0.1:4222 go run main.go

5 - Pub/Sub with NATS Broker

Use the NATS broker for pub/sub.

In code

package main

import (
    "log"
    "go-micro.dev/v6"
    "go-micro.dev/v6/broker"
    bnats "go-micro.dev/v6/broker/nats"
)

func main() {
    b := bnats.NewNatsBroker()
    svc := micro.NewService("nats-pubsub", micro.Broker(b))
    svc.Init()

    // subscribe
    _, _ = broker.Subscribe("events", func(e broker.Event) error {
        log.Printf("received: %s", string(e.Message().Body))
        return nil
    })

    // publish
    _ = broker.Publish("events", &broker.Message{Body: []byte("hello")})

    svc.Run()
}

Via environment

Run your service with env vars set:

MICRO_BROKER=nats MICRO_BROKER_ADDRESS=nats://127.0.0.1:4222 go run main.go

6 - RPC Client

Call a running service using the Go Micro client.

package main

import (
    "context"
    "fmt"
    "go-micro.dev/v6"
)

type Request struct { Name string }

type Response struct { Message string }

func main() {
    svc := micro.NewService("caller")
    svc.Init()

    req := svc.Client().NewRequest("helloworld", "Say.Hello", &Request{Name: "John"})
    var rsp Response

    if err := svc.Client().Call(context.TODO(), req, &rsp); err != nil {
        fmt.Println("error:", err)
        return
    }

    fmt.Println(rsp.Message)
}

7 - Service Discovery with Consul

Use Consul as the service registry.

In code

package main

import (
    "go-micro.dev/v6"
    "go-micro.dev/v6/registry/consul"
)

func main() {
    reg := consul.NewConsulRegistry()
    svc := micro.NewService("consul-registry", micro.Registry(reg))
    svc.Init()
    svc.Run()
}

Via environment

Run your service with env vars set:

MICRO_REGISTRY=consul MICRO_REGISTRY_ADDRESS=127.0.0.1:8500 go run main.go

8 - State with Postgres Store

Use the Postgres store for persistent key/value state.

In code

package main

import (
    "log"
    "go-micro.dev/v6"
    "go-micro.dev/v6/store"
    postgres "go-micro.dev/v6/store/postgres"
)

func main() {
    st := postgres.NewStore()
    svc := micro.NewService("postgres-store", micro.Store(st))
    svc.Init()

    _ = store.Write(&store.Record{Key: "foo", Value: []byte("bar")})
    recs, _ := store.Read("foo")
    log.Println("value:", string(recs[0].Value))

    svc.Run()
}

Via environment

Run your service with env vars set:

MICRO_STORE=postgres \
MICRO_STORE_ADDRESS=postgres://user:pass@127.0.0.1:5432/postgres \
MICRO_STORE_DATABASE=micro \
MICRO_STORE_TABLE=micro \
go run main.go