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>
169 行
5.2 KiB
Markdown
169 行
5.2 KiB
Markdown
---
|
|
layout: blog
|
|
title: "The Model Package: Client, Server, and Now Data"
|
|
permalink: /blog/6
|
|
description: "Go Micro now has a typed data model layer — define structs, get CRUD and queries, swap backends. Every service gets Client, Server, and Model."
|
|
---
|
|
|
|
# The Model Package: Client, Server, and Now Data
|
|
|
|
<img src="/images/generated/data-model.jpg" alt="The Model Package: Client, Server, and Now Data" style="width: 100%; border-radius: 8px; margin: 1rem 0 1.5rem;" />
|
|
|
|
*March 4, 2026 — By the Go Micro Team*
|
|
|
|
Go Micro has always given you `service.Client()` to call other services and `service.Server()` to handle requests. But most services also need to save and query data. Until now, that meant either using the low-level `store` package (key-value only) or wiring up your own database layer.
|
|
|
|
Today we're shipping the `model` package — a typed data model layer that completes the service trifecta: **Client, Server, Model**.
|
|
|
|
## The Problem
|
|
|
|
The existing `store` package is great for simple key-value storage, but real services need more. You need to filter by fields, paginate results, count records, and use different databases in dev vs production. Most teams end up writing their own data layer or pulling in an ORM that has nothing to do with Go Micro.
|
|
|
|
We wanted something that feels native to the framework. Define a Go struct, tag a key, and get type-safe CRUD and queries — with the same pluggable backend pattern Go Micro uses everywhere.
|
|
|
|
## Define a Struct, Get a Database
|
|
|
|
```go
|
|
type User struct {
|
|
ID string `json:"id" model:"key"`
|
|
Name string `json:"name"`
|
|
Email string `json:"email" model:"index"`
|
|
Age int `json:"age"`
|
|
}
|
|
```
|
|
|
|
The `model:"key"` tag marks your primary key. The `model:"index"` tag creates an index for faster queries. Column names come from `json` tags (or lowercased field names if no tag).
|
|
|
|
Register your type and use it:
|
|
|
|
```go
|
|
db := service.Model()
|
|
db.Register(&User{})
|
|
|
|
// Create
|
|
db.Create(ctx, &User{ID: "1", Name: "Alice", Email: "alice@example.com", Age: 30})
|
|
|
|
// Read
|
|
user := &User{}
|
|
db.Read(ctx, "1", user)
|
|
|
|
// Update
|
|
user.Name = "Alice Smith"
|
|
db.Update(ctx, user)
|
|
|
|
// Delete
|
|
db.Delete(ctx, "1", &User{})
|
|
```
|
|
|
|
No migrations. No connection setup. No configuration files. The schema is derived from your struct at startup.
|
|
|
|
## Queries That Feel Like Go
|
|
|
|
List and count with composable query options:
|
|
|
|
```go
|
|
var active []*User
|
|
|
|
// Simple equality filter
|
|
db.List(ctx, &active, model.Where("email", "alice@example.com"))
|
|
|
|
// Operators, ordering, pagination
|
|
var page []*User
|
|
db.List(ctx, &page,
|
|
model.WhereOp("age", ">=", 18),
|
|
model.OrderDesc("name"),
|
|
model.Limit(10),
|
|
model.Offset(20),
|
|
)
|
|
|
|
// Count records
|
|
total, _ := db.Count(ctx, &User{}, model.Where("age", 30))
|
|
```
|
|
|
|
Filters support `=`, `!=`, `<`, `>`, `<=`, `>=`, and `LIKE`. Everything composes — add as many query options as you need.
|
|
|
|
## Three Backends, One Interface
|
|
|
|
The model layer follows Go Micro's pluggable pattern. Same code, different backends:
|
|
|
|
**Memory** — the default. Zero config, great for development and testing:
|
|
|
|
```go
|
|
service := micro.NewService("users")
|
|
db := service.Model() // in-memory by default
|
|
db.Register(&User{})
|
|
```
|
|
|
|
**SQLite** — single-file database for local development or single-node production:
|
|
|
|
```go
|
|
db, _ := sqlite.New(model.WithDSN("file:app.db"))
|
|
service := micro.NewService("users", micro.Model(db))
|
|
```
|
|
|
|
**Postgres** — production-grade with connection pooling:
|
|
|
|
```go
|
|
db, _ := postgres.New(model.WithDSN("postgres://localhost/myapp"))
|
|
service := micro.NewService("users", micro.Model(db))
|
|
```
|
|
|
|
Start with memory in dev, switch to SQLite or Postgres for production. Your application code doesn't change.
|
|
|
|
## The Complete Service Interface
|
|
|
|
The Service interface now has three core accessors:
|
|
|
|
```go
|
|
type Service interface {
|
|
Client() client.Client // Call other services
|
|
Server() server.Server // Handle incoming requests
|
|
Model() model.Model // Save and query data
|
|
// ...
|
|
}
|
|
```
|
|
|
|
This means a typical service has everything it needs in one place:
|
|
|
|
```go
|
|
func main() {
|
|
service := micro.NewService("users", micro.Address(":9001"))
|
|
|
|
// Data layer
|
|
db := service.Model()
|
|
db.Register(&User{})
|
|
|
|
// Handler with data access
|
|
service.Handle(&UserService{db: db})
|
|
|
|
// Run
|
|
service.Run()
|
|
}
|
|
```
|
|
|
|
Call services with `service.Client()`. Handle requests with `service.Server()`. Save data with `service.Model()`. That's the complete picture.
|
|
|
|
## Multiple Models, One Database
|
|
|
|
You can create multiple typed models from the same database connection:
|
|
|
|
```go
|
|
db := service.Model()
|
|
|
|
db.Register(&User{})
|
|
db.Register(&Post{})
|
|
db.Register(&Comment{})
|
|
```
|
|
|
|
Each type gets its own table (derived from the struct name). They share the database connection.
|
|
|
|
## What's Next
|
|
|
|
The model package is production-ready with memory, SQLite, and Postgres backends. Coming soon:
|
|
|
|
- **Relationships** — define foreign keys between models
|
|
- **Migrations** — track and apply schema changes
|
|
- **Protobuf codegen** — `protoc-gen-micro` generates model code from proto definitions
|
|
|
|
See the [model documentation](https://go-micro.dev/docs/model.html) for the full API reference, or browse the [model package source](https://github.com/micro/go-micro/tree/master/model) to see the implementation.
|