自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

聊聊Go 應(yīng)用程序設(shè)計(jì)標(biāo)準(zhǔn)

開發(fā) 前端
本文旨在建議團(tuán)隊(duì)制定成員都要遵循的規(guī)則,作為團(tuán)隊(duì)的 Go 應(yīng)用程序設(shè)計(jì)標(biāo)準(zhǔn),而不是建議大家必須遵循本文介紹的 4 個(gè)規(guī)則。

1.介紹

眾所周知 Go 語言官方成員 Russ Cox 曾向 Go 社區(qū)回應(yīng)并沒有 Go 應(yīng)用程序設(shè)計(jì)標(biāo)準(zhǔn)。但是,為什么本文還要使用這個(gè)標(biāo)題呢?

因?yàn)閳F(tuán)隊(duì)達(dá)成一個(gè)共識(shí)(標(biāo)準(zhǔn)),制定一些團(tuán)隊(duì)成員都要遵循的規(guī)則,可以使我們的應(yīng)用程序更容易維護(hù)。本文介紹一下我們應(yīng)該怎么組織我們的代碼,制定團(tuán)隊(duì)的 Go 應(yīng)用程序設(shè)計(jì)標(biāo)準(zhǔn)。

需要注意的是,它不是核心 Go 開發(fā)團(tuán)隊(duì)制定的官方標(biāo)準(zhǔn)。

2.定義 domain 包

為什么需要定義 domain 包?因?yàn)槲覀冮_發(fā)的 Go 應(yīng)用程序,可能不只是包含一個(gè)功能模塊,并且可能不同的功能模塊之間還需要互相調(diào)用,所以,我們需要 domain(領(lǐng)域)包,例如我們開發(fā)一個(gè)博客應(yīng)用程序,我們的 domain 包括用戶、文章、評(píng)論等。這些不依賴我們使用的底層技術(shù)。

需要注意的是,domain 包不應(yīng)該包含方法的實(shí)現(xiàn)細(xì)節(jié),比如操作數(shù)據(jù)庫或調(diào)用其他微服務(wù),并且 domain 包不可以依賴應(yīng)用程序中的其他包。

我們可以定義 domain 包,把結(jié)構(gòu)體和接口放在 domain 包,例如:

package domain

import "context"

type User struct {
Id int64 `json:"id"`
UserName string `json:"user_name" xorm:"varchar(30) notnull default '' unique comment('用戶名')"`
Email string `json:"email" xorm:"varchar(30) not null default '' index comment('郵箱')"`
Password string `json:"password" xorm:"varchar(60) not null default '' comment('密碼')"`
Created int `json:"created" xorm:"index created"`
Updated int `json:"updated" xorm:"updated"`
Deleted int `json:"deleted" xorm:"deleted"`
}

type UserUsecase interface {
GetById(ctx context.Context, id int) (*User, error)
GetByPage(ctx context.Context, count, offset int) ([]*User, int, error)
Create(ctx context.Context, user *User) error
Delete(ctx context.Context, id int) error
Update(ctx context.Context, user *User) error
}

type UserRepository interface {
GetById(ctx context.Context, id int) (*User, error)
GetByPage(ctx context.Context, count, offset int) ([]*User, int, error)
Create(ctx context.Context, user *User) error
Delete(ctx context.Context, id int) error
Update(ctx context.Context, user *User) error
}

細(xì)心的讀者朋友們可能已經(jīng)發(fā)現(xiàn),以上代碼在「Go 語言整潔架構(gòu)實(shí)踐」一文中,它是被劃分到 models 包。是的,因?yàn)楫?dāng)時(shí)我們的示例項(xiàng)目是 TodoList,它僅包含一個(gè)功能模塊。

但是,當(dāng)我們開發(fā)一個(gè)包含多個(gè)功能模塊的應(yīng)用程序時(shí),為了方便功能模塊之間相互調(diào)用,更建議將所有功能模塊的結(jié)構(gòu)體和接口存放到 domain 包。

3.按照依賴關(guān)系劃分包

在「Go 語言整潔架構(gòu)實(shí)踐」一文中,提到在 Repository 層存放操作數(shù)據(jù)庫和調(diào)用微服務(wù)的代碼,我們可以在 Repository 層按照依賴關(guān)系劃分包,比如我們的應(yīng)用程序需要操作 MySQL 數(shù)據(jù)庫,我們可以定義一個(gè) mysql 包。

示例代碼:

package mysql

import (
"context"
"go_standard/domain"
"xorm.io/xorm"
)

type mysqlUserRepository struct {
Conn *xorm.Engine
}

func NewMysqlUserRepository(Conn *xorm.Engine) domain.UserRepository {
_ = Conn.Sync2(new(domain.User))
return &mysqlUserRepository{Conn}
}

func (m *mysqlUserRepository) GetById(ctx context.Context, id int) (res *domain.User, err error) {
// TODO::implements it
return
}

func (m *mysqlUserRepository) GetByPage(ctx context.Context, count, offset int) (data []*domain.User, nextOffset int, err error) {
// TODO::implements it
return
}

func (m *mysqlUserRepository) Create(ctx context.Context, user *domain.User) (err error) {
// TODO::implements it
return
}

func (m *mysqlUserRepository) Delete(ctx context.Context, id int) (err error) {
// TODO::implements it
return
}

func (m *mysqlUserRepository) Update(ctx context.Context, user *domain.User) (err error) {
// TODO::implements it
return
}

閱讀上面這段代碼,我們可以發(fā)現(xiàn) mysql 包主要作為 domain 包和操作數(shù)據(jù)庫的方法實(shí)現(xiàn)之間的適配器,這種包布局方式,隔離了我們 MySQL 的依賴關(guān)系,從而方便了未來遷移到其他數(shù)據(jù)庫的實(shí)現(xiàn)。比如,我們未來想把數(shù)據(jù)庫切換為 PostgreSQL,我們可以再定義一個(gè) postgresql 包,提供 PostgreSQL 的支持。

4.共享 mock 包

因?yàn)槲覀兊囊蕾図?xiàng)通過我們的 domain 包定義的接口與其他依賴項(xiàng)隔離,所以我們可以使用這些連接點(diǎn)來注入 mock 實(shí)現(xiàn)??梢允褂?mock 庫生成 mock 代碼,也可以自己編寫 mock 代碼。

5.使用 main 包將依賴關(guān)系連接起來

最后,我們使用 main 包將這些彼此孤立的包連接起來,將對(duì)象需要的依賴注入到對(duì)象中。

package main

import (
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
_userHttpDelivery "go_standard/user/delivery/http"
_userRepo "go_standard/user/repository/mysql"
_userUsecase "go_standard/user/usecase"
"xorm.io/xorm"
)

func main() {
db, err := xorm.NewEngine("mysql", "root:root@/go_standard?charset=utf8mb4")
if err != nil {
return
}
r := gin.Default()
userRepo := _userRepo.NewMysqlUserRepository(db)
userUsecase := _userUsecase.NewUserUsecase(userRepo)
_userHttpDelivery.NewUserHandler(r, userUsecase)
}

6.總結(jié)

我們遵循以上 4 個(gè)規(guī)則設(shè)計(jì) Go 應(yīng)用程序,不僅可以有效幫助我們?cè)诰帉懘a時(shí)避免循環(huán)依賴,還可以提升應(yīng)用程序的可閱讀性、可維護(hù)性和可擴(kuò)展性。

值得一提的是,本文旨在建議團(tuán)隊(duì)制定成員都要遵循的規(guī)則,作為團(tuán)隊(duì)的 Go 應(yīng)用程序設(shè)計(jì)標(biāo)準(zhǔn),而不是建議大家必須遵循本文介紹的 4 個(gè)規(guī)則。

責(zé)任編輯:武曉燕 來源: Golang語言開發(fā)棧
相關(guān)推薦

2012-02-15 14:39:55

GNOME 3

2010-03-04 10:11:17

Android手機(jī)系統(tǒng)

2012-03-30 15:47:50

ibmdw

2010-08-12 15:59:23

Flex應(yīng)用程序

2009-09-03 08:46:55

UML類圖Java

2009-02-25 14:51:05

應(yīng)用程序設(shè)計(jì)ASP.NET.NET

2010-08-04 09:34:51

Flex設(shè)計(jì)

2012-03-20 09:20:40

Go語言

2017-10-27 13:30:59

大數(shù)據(jù)MongoDBeBay

2012-06-14 09:32:13

微軟Windows 8

2010-06-09 10:53:28

UML類圖

2010-12-13 09:20:00

2021-05-21 07:59:40

應(yīng)用程序設(shè)計(jì)動(dòng)態(tài)庫函數(shù)

2009-11-03 10:12:35

2023-03-26 00:00:01

應(yīng)用程序LLM策略

2011-07-05 09:48:02

云計(jì)算遷移

2013-10-23 10:45:55

移動(dòng)中間件最佳實(shí)踐

2024-09-29 16:04:14

2023-12-07 08:22:58

Android應(yīng)用

2020-12-28 14:40:47

云計(jì)算云應(yīng)用SaaS
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)