项目文件夹

文件
Asim Aslam c7657f73f4
goreleaser / goreleaser (push) Has been cancelled
Refactor agent plan storage, update docs, and release v6 (#2977)
* 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>
2026-06-18 11:55:35 +01:00

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.