项目文件夹

文件
Asim Aslam 1bb25d6e7f Add agent platform showcase and refactor project structure (#2884)
* feat: add agent platform showcase and blog post

Add a complete platform example (Users, Posts, Comments, Mail) that
mirrors micro/blog, demonstrating how existing microservices become
AI-accessible through MCP with zero code changes.

Includes blog post "Your Microservices Are Already an AI Platform"
walking through real agent workflows: signup, content creation,
commenting, tagging, and cross-service messaging.

https://claude.ai/code/session_01GkduEhcrqcG45rdfYh8dAc

* refactor: rename handler types to drop redundant Service suffix

UserService → Users, PostService → Posts, CommentService → Comments,
MailService → Mail. Matches micro/blog naming convention.

https://claude.ai/code/session_01GkduEhcrqcG45rdfYh8dAc

* refactor: consolidate top-level directories, reduce framework bloat

Move internal/non-public packages behind internal/ or into their
parent packages where they belong:

- deploy/ → gateway/mcp/deploy/ (Helm charts belong with the gateway)
- profile/ → service/profile/ (preset plugin profiles are a service concern)
- scripts/ → internal/scripts/ (install script is not public API)
- test/ → internal/test/ (test harness is not public API)
- util/ → internal/util/ (internal helpers shouldn't be imported externally)

Also fixes CLAUDE.md merge conflict markers and updates project
structure documentation.

All import paths updated. Build and tests pass.

https://claude.ai/code/session_01GkduEhcrqcG45rdfYh8dAc

* refactor: redesign model package to match framework conventions

Rename model.Database interface to model.Model (consistent with
client.Client, server.Server, store.Store). Remove generics in
favor of interface{}-based API with reflection.

Key changes:
- model.Model interface: Register once, CRUD infers table from type
- DefaultModel + NewModel() + package-level convenience functions
- Schema registered via Register(&User{}), no per-call schema passing
- Memory implementation as default (in model package, like store)
- memory/sqlite/postgres backends updated for new interface
- protoc-gen-micro generates RegisterXModel() instead of generic factory
- All docs, blog, and README updated

https://claude.ai/code/session_01GkduEhcrqcG45rdfYh8dAc

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-05 11:21:41 +00:00

5.0 KiB

layout, title, permalink, description
layout title permalink description
blog The Model Package: Client, Server, and Now Data /blog/6 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

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

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:

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:

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:

service := micro.New("users")
db := service.Model() // in-memory by default
db.Register(&User{})

SQLite — single-file database for local development or single-node production:

db, _ := sqlite.New(model.WithDSN("file:app.db"))
service := micro.New("users", micro.Model(db))

Postgres — production-grade with connection pooling:

db, _ := postgres.New(model.WithDSN("postgres://localhost/myapp"))
service := micro.New("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:

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:

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

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 codegenprotoc-gen-micro generates model code from proto definitions

See the model documentation for the full API reference, or browse the model package source to see the implementation.