go-create-service
Go Create Service
Generate service files for GO modular architechture conventions.
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 File Layout Order
- Input/output structs
Port File Layout Order
- Interface definition (
XxxService— no suffix)
Service File Layout Order
- Implementation struct (
XxxService) - Compile-time interface assertion
- Constructor (
NewXxxService) - Methods
DTO Structure
Location: internal/modules/<module>/dto/<service_name>_dto.go
package dto
type DoSomethingInput struct {
Field string
}
Port Interface Structure
Location: internal/modules/<module>/ports/<service_name>_service.go
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.go
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
// if err != nil {
// s.logger.Error("DoSomethingService.Execute failed", logger.Error(err))
// return err
// }
return nil
}
Service Variants
Single-action service (Execute pattern)
Use Execute method with a dedicated input struct when the service does one thing.
DTO (dto/send_email_confirmation_dto.go):
type SendEmailConfirmationInput struct {
UserModel model.UserModel
ConfirmationTokenHash []byte
}
Port (ports/send_email_confirmation_service.go):
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.go):
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.
type HashService struct{}
func NewHashService() *HashService {
return &HashService{}
}
Tracing
Services performing I/O MUST use trace.Span. Pure utilities (hashing, template compilation) skip tracing.
ctx, span := trace.Span(ctx, "ServiceName.MethodName")
defer span.End()
Span name format: "StructName.MethodName"
## Naming
- Port interface: `XxxService` (in `ports` package, no suffix)
- Implementation struct: `XxxService` (in `service` package, same name — disambiguated by package)
- Constructor: `NewXxxService`, returns a pointer of the struct implementation
## Fx Wiring
Add to `internal/modules/<module>/fx.go`:
```go
fx.Provide(
fx.Annotate(
service.NewXxxService,
fx.As(new(ports.XxxService)),
),
),
Dependencies
Services depend on interfaces only. Common dependencies:
logger.Logger— structured logging- Other
ports.XxxServiceinterfaces — compose services ports.XxxRepository— data accessports.XxxCache— caching layer
Error Logging Rule
- Always use the Bricks logger package:
github.com/cristiano-pacheco/bricks/pkg/logger - Every time a service method returns an error, log it immediately before returning
- Preferred pattern:
if err != nil {
s.logger.Error("ServiceName.MethodName failed", logger.Error(err))
return err
}
Critical Rules
- Three files: DTOs in
dto/, port interface inports/, implementation inservice/ - 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
var _ ports.XxxService = (*XxxService)(nil)below the struct - Constructor: MUST return pointer
*XxxService - Tracing: Every I/O method MUST use
trace.Spanwithdefer span.End() - Context: Methods performing I/O accept
context.Contextas first parameter - No comments on implementations: Do not add redundant comments above methods in the implementations
- Add detailed comment on interfaces: Provide comprehensive comments on the port interfaces to describe their purpose and usage
- Dependencies: Always depend on port interfaces, never concrete implementations
- Error logging: Every returned error must be logged first using Bricks logger (
s.logger.Error(..., logger.Error(err)))
Workflow
- Create DTO file in
dto/<name>_dto.go(if input/output structs are needed) - Create port interface in
ports/<name>_service.go - Create service implementation in
service/<name>_service.go - Add Fx wiring to module's
module.go(orfx.go) - Run
make lintto verify - Run
make nilawayfor static analysis
More from cristiano-pacheco/ai-rules
go-unit-tests
Generate Go unit tests using testify suite/assert patterns. Use when writing test suites with mocks, testing standalone functions, or adding unit test coverage.
23go-integration-tests
Generate Go integration tests with real database/infrastructure via itestkit containers. Use when testing use cases against real databases, verifying end-to-end flows, or adding integration test coverage.
15go-create-usecase
Generate Go use cases for modular architecture using ports-based dependencies and decorator-based observability. Use when implementing business actions in internal/modules/<module>/usecase/ such as create, update, list, delete, status transitions, uploads, notifications, or any domain operation that orchestrates repositories/services.
11go-cache
Generate Redis-backed Go cache. Invoke whenever user mentions cache or Redis.
11go-chi-handler
Generate Chi HTTP handlers, use case orchestration, Use for REST endpoint handlers or web http handlers.
10creating-cursor-rules-skill
Expert guidance for creating effective Cursor IDE rules with best practices, patterns, and examples
9