如何使用Golang构建微服务Web接口_支持REST和RPC调用

Golang微服务应统一用Protocol Buffers定义契约,gin/echo处理REST对外API,gRPC处理内部高频通信,通过grpc-gateway实现双协议共存;共享service层与中间件/拦截器保障可观测性与一致性。

用 Golang 构建微服务 Web 接口,核心是把服务拆成独立、可通信的模块,同时支持 REST(面向资源、HTTP/JSON)和 RPC(面向方法、高效调用)。关键不在于堆砌框架,而在于合理分层、统一通信契约、避免重复造轮子。

选型:轻量但可扩展的组合

推荐使用 ginecho 处理 REST 请求,它们路由清晰、中间件友好;RPC 层推荐 gRPC(基于 Protocol Buffers),天然支持多语言、双向流、强类型契约。两者共存不冲突——REST 对外暴露 API,gRPC 用于服务间内部调用。

  • REST 接口走 HTTP/1.1,返回 JSON,适合前端、第三方系统集成
  • gRPC 接口走 HTTP/2,二进制传输,性能高、延迟低,适合服务间高频通信
  • 共享同一套业务逻辑(如 service 层),避免 REST handler 和 gRPC server 各写一遍业务

定义统一的数据契约(Protocol Buffers)

.proto 文件定义请求/响应结构和 RPC 方法,既是 gRPC 的接口描述,也可生成 REST 映射(通过 grpc-gateway 自动生成反向代理)。

例如:// api/v1/user.proto

syntax = "proto3";
package v1;

service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); }

message GetUserRequest { string user_id = 1; }

message GetUserResponse { string id = 1; string name = 2; int32 age = 3; }

protoc 生成 Go 代码(含 gRPC server/client + JSON mapping),再配合 grpc-gateway,就能让同一个 gRPC 方法自动响应 GET /v1/users/{user_id} 这样的 REST 请求。

启动双协议服务(HTTP + gRPC)

一个进程同时监听两个端口:一个给 REST(经 grpc-gateway 转发到 gRPC),一个直连 gRPC Server。

  • gRPC Server:绑定 :9000,注册你的 service 实现
  • HTTP Server:绑定 :8080,用 grpc-gateway 启动反向代理,转发 /v1/\*\* 到本地 gRPC 地址
  • 两者共享同一个底层 service 实例(比如 UserService{repo: userRepo}),确保逻辑一致

添加基础能力:中间件与可观测性

微服务离不开日志、链路追踪、熔断限流。Gin/Echo 支持中间件,gRPC 支持拦截器(interceptor),可以复用逻辑:

  • 统一日志:记录请求 ID、耗时、路径、状态码或错误
  • OpenTelemetry:用 otelgrpcotelgin 插件自动采集 span
  • 限流:REST 层用 golang.org/x/time/rate,gRPC 层用 interceptor 包裹
  • 错误处理:定义标准错误码(如 ErrNotFound=404),在 gateway 和 gRPC 层统一转成 HTTP 状态码或 gRPC status