go-create-service
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGo Create Service
创建Go服务
Generate service files for GO modular architechture conventions.
按照Go模块化架构规范生成服务文件。
Three-File Pattern
三文件模式
Every service requires up to three files:
- DTO structs (if needed):
internal/modules/<module>/dto/<service_name>_dto.go - Port interface:
internal/modules/<module>/ports/<service_name>_service.go - Service implementation:
internal/modules/<module>/service/<service_name>_service.go
每个服务最多需要三个文件:
- DTO结构体(如有需要):
internal/modules/<module>/dto/<service_name>_dto.go - Port接口:
internal/modules/<module>/ports/<service_name>_service.go - 服务实现:
internal/modules/<module>/service/<service_name>_service.go
DTO File Layout Order
DTO文件布局顺序
- Input/output structs
- 输入/输出结构体
Port File Layout Order
Port文件布局顺序
- Interface definition (— no suffix)
XxxService
- 接口定义(— 无后缀)
XxxService
Service File Layout Order
服务文件布局顺序
- Implementation struct ()
XxxService - Compile-time interface assertion
- Constructor ()
NewXxxService - Methods
- 实现结构体()
XxxService - 编译时接口断言
- 构造函数()
NewXxxService - 方法
DTO Structure
DTO结构
Location:
internal/modules/<module>/dto/<service_name>_dto.gogo
package dto
type DoSomethingInput struct {
Field string
}位置:
internal/modules/<module>/dto/<service_name>_dto.gogo
package dto
type DoSomethingInput struct {
Field string
}Port Interface Structure
Port接口结构
Location:
internal/modules/<module>/ports/<service_name>_service.gogo
package ports
import (
"context"
"github.com/cristiano-pacheco/pingo/internal/modules/<module>/dto"
)
type DoSomethingService interface {
Execute(ctx context.Context, input dto.DoSomethingInput) error
}位置:
internal/modules/<module>/ports/<service_name>_service.gogo
package ports
import (
"context"
"github.com/cristiano-pacheco/pingo/internal/modules/<module>/dto"
)
type DoSomethingService interface {
Execute(ctx context.Context, input dto.DoSomethingInput) error
}Service Implementation Structure
服务实现结构
Location:
internal/modules/<module>/service/<service_name>_service.gogo
package service
import (
"context"
"github.com/cristiano-pacheco/bricks/pkg/logger"
"github.com/cristiano-pacheco/bricks/pkg/otel/trace"
"github.com/cristiano-pacheco/pingo/internal/modules/<module>/dto"
"github.com/cristiano-pacheco/pingo/internal/modules/<module>/ports"
)
type DoSomethingService struct {
logger logger.Logger
// other dependencies
}
var _ ports.DoSomethingService = (*DoSomethingService)(nil)
func NewDoSomethingService(
logger logger.Logger,
) *DoSomethingService {
return &DoSomethingService{
logger: logger,
}
}
func (s *DoSomethingService) Execute(ctx context.Context, input dto.DoSomethingInput) error {
ctx, span := trace.Span(ctx, "DoSomethingService.Execute")
defer span.End()
// Business logic here
return nil
}位置:
internal/modules/<module>/service/<service_name>_service.gogo
package service
import (
"context"
"github.com/cristiano-pacheco/bricks/pkg/logger"
"github.com/cristiano-pacheco/bricks/pkg/otel/trace"
"github.com/cristiano-pacheco/pingo/internal/modules/<module>/dto"
"github.com/cristiano-pacheco/pingo/internal/modules/<module>/ports"
)
type DoSomethingService struct {
logger logger.Logger
// other dependencies
}
var _ ports.DoSomethingService = (*DoSomethingService)(nil)
func NewDoSomethingService(
logger logger.Logger,
) *DoSomethingService {
return &DoSomethingService{
logger: logger,
}
}
func (s *DoSomethingService) Execute(ctx context.Context, input dto.DoSomethingInput) error {
ctx, span := trace.Span(ctx, "DoSomethingService.Execute")
defer span.End()
// Business logic here
return nil
}Service Variants
服务变体
Single-action service (Execute pattern)
单动作服务(Execute模式)
Use method with a dedicated input struct when the service does one thing.
ExecuteDTO ():
dto/send_email_confirmation_dto.gogo
type SendEmailConfirmationInput struct {
UserModel model.UserModel
ConfirmationTokenHash []byte
}Port ():
ports/send_email_confirmation_service.gogo
type SendEmailConfirmationService interface {
Execute(ctx context.Context, input dto.SendEmailConfirmationInput) error
}当服务仅执行单一操作时,使用带专属输入结构体的方法。
ExecuteDTO():
dto/send_email_confirmation_dto.gogo
type SendEmailConfirmationInput struct {
UserModel model.UserModel
ConfirmationTokenHash []byte
}Port():
ports/send_email_confirmation_service.gogo
type SendEmailConfirmationService interface {
Execute(ctx context.Context, input dto.SendEmailConfirmationInput) error
}Multi-method service (named methods)
多方法服务(命名方法)
Use descriptive method names when the service groups related operations.
Port ():
ports/hash_service.gogo
type HashService interface {
GenerateFromPassword(password []byte) ([]byte, error)
CompareHashAndPassword(hashedPassword, password []byte) error
GenerateRandomBytes() ([]byte, error)
}当服务需要分组相关操作时,使用描述性方法名称。
Port():
ports/hash_service.gogo
type HashService interface {
GenerateFromPassword(password []byte) ([]byte, error)
CompareHashAndPassword(hashedPassword, password []byte) error
GenerateRandomBytes() ([]byte, error)
}Stateless service (no dependencies)
无状态服务(无依赖)
Omit logger and config when the service is a pure utility with no I/O.
go
type HashService struct{}
func NewHashService() *HashService {
return &HashService{}
}当服务是纯工具类且无I/O操作时,可省略日志和配置。
go
type HashService struct{}
func NewHashService() *HashService {
return &HashService{}
}Tracing
链路追踪
Services performing I/O MUST use . Pure utilities (hashing, template compilation) skip tracing.
trace.Spango
ctx, span := trace.Span(ctx, "ServiceName.MethodName")
defer span.End()Span name format:
"StructName.MethodName"undefined执行I/O操作的服务必须使用。纯工具类服务(如哈希、模板编译)可跳过链路追踪。
trace.Spango
ctx, span := trace.Span(ctx, "ServiceName.MethodName")
defer span.End()Span名称格式:
"StructName.MethodName"Naming
命名规范
- Port interface: (in
XxxServicepackage, no suffix)ports - Implementation struct: (in
XxxServicepackage, same name — disambiguated by package)service - Constructor: , returns a pointer of the struct implementation
NewXxxService
- Port接口:(位于
XxxService包,无后缀)ports - 实现结构体:(位于
XxxService包,同名——通过包名区分)service - 构造函数:,返回结构体指针
NewXxxService
Fx Wiring
Fx依赖注入配置
Add to :
internal/modules/<module>/fx.gogo
fx.Provide(
fx.Annotate(
service.NewXxxService,
fx.As(new(ports.XxxService)),
),
),添加至:
internal/modules/<module>/fx.gogo
fx.Provide(
fx.Annotate(
service.NewXxxService,
fx.As(new(ports.XxxService)),
),
),Dependencies
依赖规则
Services depend on interfaces only. Common dependencies:
- — structured logging
logger.Logger - Other interfaces — compose services
ports.XxxService - — data access
ports.XxxRepository - — caching layer
ports.XxxCache
服务仅依赖接口。常见依赖包括:
- — 结构化日志
logger.Logger - 其他接口 — 服务组合
ports.XxxService - — 数据访问
ports.XxxRepository - — 缓存层
ports.XxxCache
Critical Rules
核心规则
- Three files: DTOs in , port interface in
dto/, implementation inports/service/ - Interface in ports: Interface lives in
ports/<name>_service.go - DTOs in dto: Input/output structs live in
dto/<name>_dto.go - Interface assertion: Add below the struct
var _ ports.XxxService = (*XxxService)(nil) - Constructor: MUST return pointer
*XxxService - Tracing: Every I/O method MUST use with
trace.Spandefer span.End() - Context: Methods performing I/O accept as first parameter
context.Context - No comments: Do not add redundant comments above methods
- Dependencies: Always depend on port interfaces, never concrete implementations
- 三文件结构:DTO存放于目录,Port接口存放于
dto/目录,实现代码存放于ports/目录service/ - 接口位置:接口定义在中
ports/<name>_service.go - DTO位置:输入/输出结构体存放于中
dto/<name>_dto.go - 接口断言:在结构体定义下方添加
var _ ports.XxxService = (*XxxService)(nil) - 构造函数:必须返回指针
*XxxService - 链路追踪:每个I/O方法必须使用并配合
trace.Spandefer span.End() - 上下文参数:执行I/O操作的方法必须将作为第一个参数
context.Context - 避免冗余注释:不要在方法上方添加冗余注释
- 依赖原则:始终依赖Port接口,而非具体实现
Workflow
工作流程
- Create DTO file in (if input/output structs are needed)
dto/<name>_dto.go - Create port interface in
ports/<name>_service.go - Create service implementation in
service/<name>_service.go - Add Fx wiring to module's (or
module.go)fx.go - Run to verify
make lint - Run for static analysis
make nilaway
- 在中创建DTO文件(如需输入/输出结构体)
dto/<name>_dto.go - 在中创建Port接口
ports/<name>_service.go - 在中创建服务实现
service/<name>_service.go - 将Fx依赖注入配置添加至模块的(或
module.go)fx.go - 运行进行验证
make lint - 运行进行静态分析
make nilaway