はじめに
GoでDTOを使用する方法についてメモ。
以前、NestJSでバリデーションを行ったときにもDTOを利用したので、興味がある方はこちらもご覧ください。
DTOとは
ドメイン層をインフラ層(DB)から分離したいときに使います。
例えば、以下のようなモデルが定義されているとします。
このとき、DBでstatus = "0" or "1"
が管理されているとしても、DTOを使用すれば、ドメイン側ではStatus = "active" or "inactive"
などに変換して取り扱うことができます。
domain/customer.go
type Customer struct {
Id string
Name string
City string
Zipcode string
DateofBirth string
Status string
}
また、ドメインモデルの中にインフラ層のタグが入らないようにする、ドメインモデルの中にDB用のID, CreatedAt, UpdatedAtが入らないようにする、といったケースでもDTOは使用されるようです。
実装
DTOの構造体を新しくつくります。
dto/customerResponse.go
package dto
type CustomerResponse struct {
Id string `json:"customer_id"`
Name string `json:"full_name"`
City string `json:"city"`
Zipcode string `json:"zipcode"`
DateofBirth string `json:"date_of_birth"`
Status string `json:"status"`
}
ドメインモデルからDTOに変換するメソッドToDto()
をつくります。
また、statusAsText()
でStatus
を"active" or "inactive"
に変換します。
domain/customer.go
func (c Customer) statusAsText() string {
statusAsText := "active"
if c.Status == "0" {
statusAsText = "inactive"
}
return statusAsText
}
func (c Customer) ToDto() dto.CustomerResponse {
return dto.CustomerResponse{
Id: c.Id,
Name: c.Name,
City: c.City,
Zipcode: c.Zipcode,
DateofBirth: c.DateofBirth,
Status: c.Status,
}
}
そして、サービス層では、DBから取得したデータをc.ToDto()
でDTOに変換して、response
として返します。
service/customerService.go
func (s DefaultCustomerService) GetCustomer(id string) (*dto.CustomerResponse, *errs.AppError) {
c, err :=s.repo.ById(id)
if err != nil {
return nil, err
}
response := c.ToDto()
return &response, nil
}
参考資料