sequence
This paper mainly appreciates the practice of Go-bank-Transfer for Clean Architecture
The project structure
├ ─ ─ adapter │ ├ ─ ─ API │ │ ├ ─ ─ action │ │ ├ ─ ─ logging │ │ ├ ─ ─ middleware │ │ └ ─ ─ the response │ ├ ─ ─ logger │ ├ ─ ─ presenter │ ├── Repository │ ├─ Heavy ├─ Infrastructure │ ├─ Database │ ├─ router │ ├─ Validation ├─ usecaseCopy the code
There are four layers: Adapter, Domain, Infrastructure, and usecase
domain
account
type AccountID string
func (a AccountID) String() string {
return string(a)
}
type (
AccountRepository interface {
Create(context.Context, Account) (Account, error)
UpdateBalance(context.Context, AccountID, Money) error
FindAll(context.Context) ([]Account, error)
FindByID(context.Context, AccountID) (Account, error)
FindBalance(context.Context, AccountID) (Account, error)
}
Account struct {
id AccountID
name string
cpf string
balance Money
createdAt time.Time
}
)
func NewAccount(ID AccountID, name, CPF string, balance Money, createdAt time.Time) Account {
return Account{
id: ID,
name: name,
cpf: CPF,
balance: balance,
createdAt: createdAt,
}
}
func (a *Account) Deposit(amount Money) {
a.balance += amount
}
func (a *Account) Withdraw(amount Money) error {
if a.balance < amount {
return ErrInsufficientBalance
}
a.balance -= amount
return nil
}
func (a Account) ID() AccountID {
return a.id
}
func (a Account) Name() string {
return a.name
}
func (a Account) CPF() string {
return a.cpf
}
func (a Account) Balance() Money {
return a.balance
}
func (a Account) CreatedAt() time.Time {
return a.createdAt
}
func NewAccountBalance(balance Money) Account {
return Account{balance: balance}
}
Copy the code
Account defines the AccountRepository interface and account type. It also provides the Withdraw and Deposit methods
transfer
type TransferID string
func (t TransferID) String() string {
return string(t)
}
type (
TransferRepository interface {
Create(context.Context, Transfer) (Transfer, error)
FindAll(context.Context) ([]Transfer, error)
WithTransaction(context.Context, func(context.Context) error) error
}
Transfer struct {
id TransferID
accountOriginID AccountID
accountDestinationID AccountID
amount Money
createdAt time.Time
}
)
func NewTransfer(
ID TransferID,
accountOriginID AccountID,
accountDestinationID AccountID,
amount Money,
createdAt time.Time,
) Transfer {
return Transfer{
id: ID,
accountOriginID: accountOriginID,
accountDestinationID: accountDestinationID,
amount: amount,
createdAt: createdAt,
}
}
func (t Transfer) ID() TransferID {
return t.id
}
func (t Transfer) AccountOriginID() AccountID {
return t.accountOriginID
}
func (t Transfer) AccountDestinationID() AccountID {
return t.accountDestinationID
}
func (t Transfer) Amount() Money {
return t.amount
}
func (t Transfer) CreatedAt() time.Time {
return t.createdAt
}
Copy the code
Transfer defines the TransferRepository interface and transfer type
usecase
➜ usecase git:(master) ├─ create_account.go ├─ create_account_test. Go ├─ create_account_test Create_transfer_test. Go ├── Find_account_balance. Go ├─ find_account_balance_Test. Go ├─ Find_account_balance_test ├── ├─ ├─ ├─ ├.goCopy the code
This layer defines CreateAccountUseCase and CreateAccountPresenter, CreateTransferUseCase and CreateTransferPresenter, and FindAccountBalanceUseCas E and FindAccountBalancePresenter, FindAllAccountUseCase and FindAllAccountPresenter, FindAllTransferUseCase and FindAllTransferPresen Ter interface
adapter
➜ adapter git:(master) tree. ├─ API │ ├─ action │ ├─ go │ ├─ create_account_test Go │ ├─ Heavy Metal Guitar School. Go │ ├─ Heavy metal Guitar School. Go │ ├─ Heavy metal Guitar School │ │ ├ ─ ─ find_all_account. Go │ │ ├ ─ ─ find_all_account_test. Go │ │ ├ ─ ─ find_all_transfer. Go │ │ ├ ─ ─ Go │ ├─ ├─ ├─ ├─ go │ ├─ go │ ├─ go │ ├─ go │ ├─ go │ ├─ go │ ├─ go │ ├─ go │ ├─ go │ ├─ Info. Go │ ├ ─ ─ middleware │ │ └ ─ ─ logger. Go │ └ ─ ─ the response │ ├ ─ ─ error. Go │ └ ─ ─ success. Go ├ ─ ─ logger │ └ ─ ─ logger. Go ├ ─ ─ Go │ ├─ Create_Transfer. Go │ ├─ Create_transfer. Go │ ├─ Create_transfer_test Go │ ├─ Heavy Metal Guitar School ─ Heavy metal Guitar School. Go │ Heavy metal Guitar School ─ Heavy metal Guitar School │ ├ ─ ─ find_all_transfer. Go │ └ ─ ─ find_all_transfer_test. Go ├ ─ ─ the repository │ ├ ─ ─ account_mongodb. Go │ ├ ─ ─ Account_postgres. Go │ ├ ─ ─ no. Go │ ├ ─ ─ SQL. Go │ ├ ─ ─ transfer_mongodb. Go │ └ ─ ─ transfer_postgres. Go └ ─ ─ the validator └ ─ ─ validator.goCopy the code
The Adapter layer implements the interface defined by the Domain and usecase layer
summary
Go-bank-transfer project defines model and Repository interface in domain layer, usecase layer defines USecase and Presenter interface, and at the same time calls domain layer to realize business choreography. Adapter implements the interfaces defined by the two layers above.
doc
- go-bank-transfer