项目文件夹

文件
Asim Aslam d2036b880d Claude/update docs roadmap f zd2 j (#2873)
* docs: update all four documentation guides and mark Q2 complete

- ai-native-services: add WithMCP one-liner, standalone gateway,
  WebSocket client example, and OpenTelemetry observability section
- mcp-security: add OTel distributed tracing, WebSocket authentication
  (connection-level and per-message), DeniedReason audit field
- tool-descriptions: add manual overrides with WithEndpointDocs and
  export formats section
- agent-patterns: add LangChain/LlamaIndex SDK pattern and standalone
  gateway production pattern with Docker example
- Update roadmap: mark Q2 documentation as complete, Q2 at 100%
- Update status: reflect all recent completions, shift priorities

https://claude.ai/code/session_01GkduEhcrqcG45rdfYh8dAc

* feat: add agent demo example and blog post

Add examples/agent-demo with a multi-service project management app
(projects, tasks, team) that demonstrates AI agents interacting with
Go Micro services through MCP. Includes seed data and example prompts.

Add blog post 4 "Agents Meet Microservices: A Hands-On Demo" walking
through the example code and showing cross-service agent workflows.

https://claude.ai/code/session_01GkduEhcrqcG45rdfYh8dAc

* feat: enable multiple services in a single binary

Remove global state mutations from service and cmd option functions so
that configuring one service no longer overwrites another's settings.

Key changes:
- service/options.go: remove all DefaultXxx global writes from option
  functions; newOptions() now creates fresh Server, Client, Store, and
  Cache per service while sharing Registry, Broker, and Transport
- cmd/cmd.go: newCmd() uses local copies instead of pointers to package
  globals; Before() no longer mutates DefaultXxx vars
- cmd/options.go: remove global mutations from all option functions
- service/service.go: export ServiceImpl type for cross-package use
- service/group.go: new Group type for multi-service lifecycle
- micro.go: add Start/Stop to Service interface, expose Group and
  NewGroup convenience function
- examples/multi-service: working example with two services

https://claude.ai/code/session_01GkduEhcrqcG45rdfYh8dAc

* docs: highlight multi-service binary support

Add multi-service section to README with code example, update features
list, add to examples index, and note in status summary.

https://claude.ai/code/session_01GkduEhcrqcG45rdfYh8dAc

* feat: unify service API and clean up developer experience

- Unified service creation: micro.New("name", opts...) as canonical API
- Clean handler registration: service.Handle(handler, opts...) accepts
  server.HandlerOption args directly, no need to reach through Server()
- Unexported serviceImpl: users interact through Service interface only
- Service groups use Service interface (not concrete type)
- Fixed Stop() to properly propagate BeforeStop/AfterStop errors
- Fixed store init: error-level log instead of fatal on init failure
- Updated all examples to use consistent patterns
- Updated README, getting-started, MCP docs, and guides
- Added blog post about the DX cleanup

https://claude.ai/code/session_01GkduEhcrqcG45rdfYh8dAc

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-04 11:13:27 +00:00

4.0 KiB

layout, title, permalink, description
layout title permalink description
blog Developer Experience Cleanup: One Way to Do Things /blog/5 Unified service creation, cleaner handler registration, and modular monolith support — the Go Micro DX overhaul

Developer Experience Cleanup: One Way to Do Things

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.New(), 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:

// Old: three equivalent patterns
service := micro.New("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:

service := micro.New("greeter")
service := micro.New("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.New().

Clean Handler Registration

Registering handlers used to require reaching through to the server:

// 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:

// 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:

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):

users := micro.New("users", micro.Address(":9001"))
orders := micro.New("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:

service := micro.New("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.New("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 and the agent demo for working examples.