Go 应用程序设计标准

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: Go 应用程序设计标准

介绍

众所周知 Go 语言官方成员 Russ Cox 曾向 Go 社区回应并没有 Go 应用程序设计标准。但是,为什么本文还要使用这个标题呢?

因为团队达成一个共识(标准),制定一些团队成员都要遵循的规则,可以使我们的应用程序更容易维护。本文介绍一下我们应该怎么组织我们的代码,制定团队的 Go 应用程序设计标准。

需要注意的是,它不是核心 Go 开发团队制定的官方标准。

定义 domain 包

为什么需要定义 domain 包?因为我们开发的 Go 应用程序,可能不只是包含一个功能模块,并且可能不同的功能模块之间还需要互相调用,所以,我们需要 domain(领域)包,例如我们开发一个博客应用程序,我们的 domain 包括用户、文章、评论等。这些不依赖我们使用的底层技术。

需要注意的是,domain 包不应该包含方法的实现细节,比如操作数据库或调用其他微服务,并且 domain 包不可以依赖应用程序中的其他包。

我们可以定义 domain 包,把结构体和接口放在 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
}

细心的读者朋友们可能已经发现,以上代码在「Go 语言整洁架构实践」一文中,它是被划分到 models 包。是的,因为当时我们的示例项目是 TodoList,它仅包含一个功能模块。

但是,当我们开发一个包含多个功能模块的应用程序时,为了方便功能模块之间相互调用,更建议将所有功能模块的结构体和接口存放到 domain 包。

03

按照依赖关系划分包

在「Go 语言整洁架构实践」一文中,提到在 Repository 层存放操作数据库和调用微服务的代码,我们可以在 Repository 层按照依赖关系划分包,比如我们的应用程序需要操作 MySQL 数据库,我们可以定义一个 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
}

阅读上面这段代码,我们可以发现 mysql 包主要作为 domain 包和操作数据库的方法实现之间的适配器,这种包布局方式,隔离了我们 MySQL 的依赖关系,从而方便了未来迁移到其他数据库的实现。比如,我们未来想把数据库切换为 PostgreSQL,我们可以再定义一个 postgresql 包,提供 PostgreSQL 的支持。

04

共享 mock 包

因为我们的依赖项通过我们的 domain 包定义的接口与其他依赖项隔离,所以我们可以使用这些连接点来注入 mock 实现。可以使用 mock 库生成 mock 代码,也可以自己编写 mock 代码。

05

使用 main 包将依赖关系连接起来

最后,我们使用 main 包将这些彼此孤立的包连接起来,将对象需要的依赖注入到对象中。

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)
}

06

总结

我们遵循以上 4 个规则设计 Go 应用程序,不仅可以有效帮助我们在编写代码时避免循环依赖,还可以提升应用程序的可阅读性、可维护性和可扩展性。

值得一提的是,本文旨在建议团队制定成员都要遵循的规则,作为团队的 Go 应用程序设计标准,而不是建议大家必须遵循本文介绍的 4 个规则。

推荐阅读:


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
4月前
|
Cloud Native Go 开发工具
不改一行代码轻松玩转 Go 应用微服务治理
为了更好的进行 Go 应用微服务治理,提高研发效率和系统稳定性,本文将介绍 MSE 微服务治理方案,无需修改业务代码,实现治理能力。
19864 19
|
4月前
|
数据采集 网络协议 测试技术
使用Go Validator在Go应用中有效验证数据
使用Go Validator在Go应用中有效验证数据
|
24天前
|
缓存 监控 前端开发
在 Go 语言中实现 WebSocket 实时通信的应用,包括 WebSocket 的简介、Go 语言的优势、基本实现步骤、应用案例、注意事项及性能优化策略,旨在帮助开发者构建高效稳定的实时通信系统
本文深入探讨了在 Go 语言中实现 WebSocket 实时通信的应用,包括 WebSocket 的简介、Go 语言的优势、基本实现步骤、应用案例、注意事项及性能优化策略,旨在帮助开发者构建高效稳定的实时通信系统。
74 1
|
1月前
|
监控 Go API
Go语言在微服务架构中的应用实践
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出,成为构建微服务的理想选择。本文将探讨Go语言在微服务架构中的应用实践,包括Go语言的特性如何适应微服务架构的需求,以及在实际开发中如何利用Go语言的特性来提高服务的性能和可维护性。我们将通过一个具体的案例分析,展示Go语言在微服务开发中的优势,并讨论在实际应用中可能遇到的挑战和解决方案。
|
1月前
|
Go 数据处理 API
Go语言在微服务架构中的应用与优势
本文摘要采用问答形式,以期提供更直接的信息获取方式。 Q1: 为什么选择Go语言进行微服务开发? A1: Go语言的并发模型、简洁的语法和高效的编译速度使其成为微服务架构的理想选择。 Q2: Go语言在微服务架构中有哪些优势? A2: 主要优势包括高性能、高并发处理能力、简洁的代码和强大的标准库。 Q3: 文章将如何展示Go语言在微服务中的应用? A3: 通过对比其他语言和展示Go语言在实际项目中的应用案例,来说明其在微服务架构中的优势。
|
2月前
|
Cloud Native Go API
Go语言在微服务架构中的创新应用与实践
本文深入探讨了Go语言在构建高效、可扩展的微服务架构中的应用。Go语言以其轻量级协程(goroutine)和强大的并发处理能力,成为微服务开发的首选语言之一。通过实际案例分析,本文展示了如何利用Go语言的特性优化微服务的设计与实现,提高系统的响应速度和稳定性。文章还讨论了Go语言在微服务生态中的角色,以及面临的挑战和未来发展趋势。
|
26天前
|
SQL 监控 算法
为Go应用无侵入地添加任意代码
这篇文章旨在提供技术深度和实践指南,帮助开发者理解并应用这项创新技术来提高Golang应用的监控与服务治理能力。在接下来的部分,我们将通过一些实际案例,进一步展示如何在不同场景中应用这项技术,提供更多实践启示。
|
2月前
|
运维 Go 开发者
Go语言在微服务架构中的应用与优势
本文深入探讨了Go语言在构建微服务架构中的独特优势和实际应用。通过分析Go语言的核心特性,如简洁的语法、高效的并发处理能力以及强大的标准库支持,我们揭示了为何Go成为开发高性能微服务的首选语言。文章还详细介绍了Go语言在微服务架构中的几个关键应用场景,包括服务间通信、容器化部署和自动化运维等,旨在为读者提供实用的技术指导和启发。
|
2月前
|
负载均衡 Go API
探索Go语言在微服务架构中的应用与优势
在这篇技术性文章中,我们将深入探讨Go语言(又称为Golang)在构建微服务架构时的独特优势。文章将通过对比分析Go语言与其他主流编程语言,展示Go在并发处理、性能优化、以及开发效率上的优势。同时,我们将通过一个实际的微服务案例,详细说明如何利用Go语言构建高效、可扩展的微服务系统。
|
2月前
|
安全 Go 云计算
探索Go语言在微服务架构中的应用与优势
在本文中,我们将深入探讨Go语言(又称为Golang)在构建微服务架构中的独特优势。文章将分析Go语言的并发模型、简洁的语法以及高效的编译速度,以及这些特性如何使其成为微服务架构的理想选择。我们将通过一个简单的微服务示例,展示Go语言在实际开发中的表现,并讨论其在性能和可维护性方面的优势。