micro--go-micro
c7657f73f4
goreleaser / goreleaser (push) Has been cancelled
* test(harness): read agent plan from the scoped store
The store-scoping change moved an agent's plan from the default table
key agent/{name}/plan to its own table (database "agent", table {name},
key "plan"). The plan-delegate harness tests still read the old key and
failed with 'not found'; read through store.Scope(mem, "agent", name)
like the agent does.
* docs: orient agents-first across README, landing, and docs overview
Lead with agents (then services and flows), surface MCP + A2A as the
interop story, and frame agents as services. Landing hero and feature
grid reordered agents-first with an A2A gateway card.
* v6: module path go-micro.dev/v6, TLS secure by default, NewService
Cut v6. Three breaking changes, bundled so the major bump is paid once:
- Module path go-micro.dev/v5 -> go-micro.dev/v6 across all imports + go.mod.
- TLS verification on by default (was off). MICRO_TLS_SECURE removed;
MICRO_TLS_INSECURE=true opts out for self-signed/dev.
- micro.NewService(name, opts...) is the canonical service constructor,
symmetric with NewAgent/NewFlow; micro.New kept as a deprecated alias;
the old name-less NewService(opts...) removed. Generators emit NewService.
Also ports the JWT auth token provider in-module (go-micro.dev/v6/auth/jwt/token
on golang-jwt/jwt/v5), dropping the v5-pinned github.com/micro/plugins/v5/auth/jwt
and the deprecated dgrijalva/jwt-go.
Docs/README/landing updated to v6 and @latest; v5->v6 migration guide added;
CHANGELOG cut as [6.0.0]. Blog posts left at their historical versions.
---------
Co-authored-by: Claude <noreply@anthropic.com>
115 行
4.3 KiB
Markdown
115 行
4.3 KiB
Markdown
---
|
|
layout: blog
|
|
title: "Developer Experience Cleanup: One Way to Do Things"
|
|
permalink: /blog/5
|
|
description: "Unified service creation, cleaner handler registration, and modular monolith support — the Go Micro DX overhaul"
|
|
---
|
|
|
|
# Developer Experience Cleanup: One Way to Do Things
|
|
|
|
<img src="/images/generated/blog-dx.jpg" alt="Developer Experience Cleanup: One Way to Do Things" style="width: 100%; border-radius: 8px; margin: 1rem 0 1.5rem;" />
|
|
|
|
*March 4, 2026 — By the Go Micro Team*
|
|
|
|
Go Micro has always prioritized getting out of your way. But over time, the API accumulated multiple ways to do the same thing — `micro.NewService()`, `micro.NewService()`, `service.New()`, three different handler registration patterns. If you're building something for AI agents or running a modular monolith, you shouldn't have to choose between equivalent APIs.
|
|
|
|
We've cleaned it up. Here's what changed and why.
|
|
|
|
## One Way to Create a Service
|
|
|
|
Before, there were three ways to create a service:
|
|
|
|
```go
|
|
// Old: three equivalent patterns
|
|
service := micro.NewService("greeter") // name only
|
|
service := micro.NewService(micro.Name("greeter")) // options only
|
|
service := service.New(service.Name("greeter")) // internal package
|
|
```
|
|
|
|
Now there's one canonical pattern:
|
|
|
|
```go
|
|
service := micro.NewService("greeter")
|
|
service := micro.NewService("greeter", micro.Address(":8080"))
|
|
```
|
|
|
|
Name is always the first argument. Options follow. `NewService` still works (it's deprecated, not removed), but every example, doc, and guide now uses `micro.NewService()`.
|
|
|
|
## Clean Handler Registration
|
|
|
|
Registering handlers used to require reaching through to the server:
|
|
|
|
```go
|
|
// Old: verbose, leaks abstraction
|
|
handler := service.Server().NewHandler(
|
|
&TaskService{tasks: make(map[string]*Task)},
|
|
server.WithEndpointScopes("TaskService.Create", "tasks:write"),
|
|
)
|
|
service.Server().Handle(handler)
|
|
```
|
|
|
|
Now `service.Handle()` accepts handler options directly:
|
|
|
|
```go
|
|
// New: clean, one call
|
|
service.Handle(
|
|
&TaskService{tasks: make(map[string]*Task)},
|
|
server.WithEndpointScopes("TaskService.Create", "tasks:write"),
|
|
)
|
|
```
|
|
|
|
For the common case with no options, it's just:
|
|
|
|
```go
|
|
service.Handle(new(Greeter))
|
|
```
|
|
|
|
## Modular Monoliths with Service Groups
|
|
|
|
Run multiple services in a single binary. Each service gets isolated state (server, client, store, cache) while sharing infrastructure (registry, broker, transport):
|
|
|
|
```go
|
|
users := micro.NewService("users", micro.Address(":9001"))
|
|
orders := micro.NewService("orders", micro.Address(":9002"))
|
|
|
|
users.Handle(new(Users))
|
|
orders.Handle(new(Orders))
|
|
|
|
g := micro.NewGroup(users, orders)
|
|
g.Run()
|
|
```
|
|
|
|
Start as a monolith, split into separate binaries when you need independent scaling. The Group handles signals and coordinated shutdown — all services start together and stop together.
|
|
|
|
## MCP Integration in One Line
|
|
|
|
Every service is automatically an MCP tool. Add a gateway alongside your service with one option:
|
|
|
|
```go
|
|
service := micro.NewService("greeter",
|
|
micro.Address(":9090"),
|
|
mcp.WithMCP(":3000"),
|
|
)
|
|
|
|
service.Handle(new(Greeter))
|
|
service.Run()
|
|
```
|
|
|
|
Your Go comments become tool descriptions. Your struct tags become parameter schemas. No glue code.
|
|
|
|
## Bug Fixes
|
|
|
|
- **Stop() error handling**: Previously, `Stop()` would silently swallow errors from `BeforeStop` hooks. Now all errors are properly propagated.
|
|
- **Store initialization**: Fatal-level log on store init failure changed to error-level — a store init failure shouldn't crash your service.
|
|
- **Service interface**: The internal implementation is now properly unexported. Users interact through the `service.Service` interface, not a concrete type.
|
|
|
|
## What This Means for You
|
|
|
|
If you're building new services, use `micro.NewService("name", opts...)` and `service.Handle()`. That's it.
|
|
|
|
If you have existing code using `micro.NewService()` or `service.Server().Handle()`, everything still works — we didn't break anything. But the docs, examples, and guides all point to the new patterns now.
|
|
|
|
The goal is simple: when someone asks "how do I create a service?", there should be exactly one answer.
|
|
|
|
See the updated [Getting Started guide](https://go-micro.dev/docs/getting-started.html) and the [agent demo](https://github.com/micro/go-micro/tree/master/examples/agent-demo) for working examples.
|