
The related code is on GitHub: GoKitAddSrv. Different folders represent different chapters, and you can run them directly with go run ..
It is written fairly simply; as long as it runs, that is enough. Please excuse the bugs and any convention issues!
Introduction
Strictly speaking, go-kit is not exactly a complete framework; it is more like a toolbox or a collection of libraries. The official description calls it a collection of packages and best practices.

It provides all the standard components for building microservices and adopts a clean architecture and an onion structure. It does not pursue development speed; instead, it enforces a three-layer architecture, strictly dividing the application into a business logic layer (Service), an endpoint layer that acts as an adapter (Endpoint), and a transport layer that handles protocols (Transport), completely decoupling business logic from network communication.
Core structure - the three-layer model

Transport
This is the outermost structure. It handles the specific network protocol, usually HTTP and RPC. Its main function is encoding and decoding: it parses incoming requests, such as JSON, into Go structs that the Endpoint can understand, then calls the Endpoint layer, and encodes the results obtained from the Endpoint layer and sends them to the client.
Endpoint
This is the middle layer connecting business logic and the network. It is responsible for wrapping the various methods in the Service layer into a unified standard function signature, which is then handed to the Transport layer to call.
// Endpoint定义
type Endpoint func(ctx context.Context, request interface{}) (response interface{}, err error)
At this layer, all calls are abstracted into the same form. Middleware is usually mounted at this layer. One set of middleware can be applied to all interfaces.
Service
The business logic layer, Service, only considers the implementation of specific business logic. It only needs to define and implement interfaces; it does not need to consider protocols or network services.
Demo - implementing a simple adder
HTTP
Description
-
Define an interface in the Service layer that contains two methods
-
Add implements addition for the int type
-
Concat implements addition for the string type
-
The basic process is to define the interface and implement it
-
-
In the Endpoint layer, define structs for the request and response data, and wrap the Service layer methods
- The basic process is to define the structs and wrap the methods
-
In the Transport layer, handle the specific protocol and respond
-
Implement encoding and decoding
-
Implement the Handler
-
Define routes and ports
-
…
-
Testing
Use Postman for testing.


RPC
gRPC is used here.
Description
-
Create the proto file
-
Create a proto folder
-
Write a proto file in the folder, defining the service and message
-
Run the protoc command to generate Go files
protoc -I=proto --go_out=proto --go_opt=paths=source_relative --go-grpc_out=proto --go-grpc_opt=paths=source_relative proto/addsrv.proto
-
-
Define an interface in the Service layer that contains two methods
-
Add implements addition for the int type
-
Concat implements addition for the string type
-
The basic process is to define the interface and implement it
-
-
In the Endpoint layer, define structs for the request and response data, and wrap the Service layer methods
- The basic process is to define the structs and wrap the methods
-
In the Transport layer, handle the specific protocol and respond
-
Implement RPC encoding and decoding
-
Implement the Handler
-
Implement the protobuf interface
-
…
-
Testing
Use Postman for testing.


Splitting the project structure
Following the three-layer structure designed by go-kit, we split the original three separate folders into layers. The specific directory structure is as follows:

Middleware
Logging
-
Create a global logger
-
Pass the logger in when implementing the interface
-
Define a logging interface, add the application interface and the logger to it, and then implement the methods
// go-kit官方设计
type logMiddleware struct {
logger log.Logger
next AddService
}
A simple implementation of adding logging middleware to the project is shown.

Rate limiting
Add rate-limiting middleware; only one request per second is allowed.
In real business scenarios, finer-grained limits can be applied to individual users.
A simple implementation of adding rate-limiting middleware to the project is shown.


Metrics collection
Use the metrics package to record statistics about the runtime behavior of the service, such as counting the number of jobs processed, recording the duration after a request completes, and tracking the number of operations in progress, among other things.
A simple implementation of adding metrics collection middleware to the project is shown.


Service calls
The call is implemented by constructing a struct that includes the current service and the called service (set to the endpoint.Endpoint type).
A simple implementation is shown.


Service discovery and load balancing
For installing and using Consul, see: Consul.
Go kit provides corresponding mechanisms for service discovery and load balancing.
-
Go kit provides a factory function, Factory, which converts an instance string (for example, host:port) into a specific endpoint. An instance that provides multiple endpoints requires multiple factory functions. The factory function also returns an io.Closer that is called when the instance disappears and needs to be cleaned up.
-
Go kit provides a basic load balancer, and you can also implement your own.
-
The retry strategy wraps the load balancer and returns an available endpoint. The retry strategy retries failed requests until the maximum number of attempts or the timeout is reached.
// 工厂函数
type Factory func(instance string) (endpoint.Endpoint, io.Closer, error)
// 负载均衡
import "github.com/go-kit/kit/sd/lb"
balancer := lb.NewRoundRobin(endpointer)
// 重试
func Retry(max int, timeout time.Duration, lb Balancer) endpoint.Endpoint
import "github.com/go-kit/kit/sd/lb"
retry := lb.Retry(3, 500*time.Millisecond, balancer)
Below is a simple implementation.
I started two trim_service instances in two separate terminals; calls automatically round-robin between them.


References
Go kit tutorial 01 — Basic example
Go kit tutorial 03 — Code layering
Go kit tutorial 04 — Middleware and logging