Golang中这是什么架构?

Golang中这是什么架构? 你好,我一直使用这种架构,但不知道它是否有名称,或者这样使用是否合适。

image

4 回复

是的,每家公司都有自己的指南,类似这样的,比如 Uber 的指南。

https://github.com/uber-go/guide/blob/master/style.md

更多关于Golang中这是什么架构?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


看起来你在你的Go项目(我猜是Web项目)中使用了MVC方法。

在Go的世界里,Go团队并没有规定好/坏/推荐的项目结构,但GitHub上有一个仓库你可以参考一下:

老实说,你可以探索GitHub和一些流行的Go项目,以便更好地理解项目结构,并选择一个适合你需求的。

golang-standards/project-layout 实际上是一个广为人知且具有误导性的例子,它根本不是一个“标准”项目布局的范例。请参阅 rsc 创建的此问题。说它“不是官方标准”并不完全准确,更准确的说法是 Go 团队积极不鼓励使用它。话虽如此,如果你有一个适合你和你的团队的项目布局,那就使用它。

我唯一尝试遵循的原则是:

  • 尽可能保持简单,直到需要复杂化为止。我通常从根目录下只有一个 main.go 文件开始,然后随着项目不可避免地增长而重新评估。
  • 仔细考虑包的职责分离可以解决大多数难以处理的代码问题。
  • 如果我有一个包含多个可执行文件的单体应用,我会坚持让每个可执行文件都位于 /cmd 文件夹的子文件夹中。这似乎是一个相当标准的做法(至少在我所处的圈子里是这样;你的情况可能有所不同!)。

总之,原帖作者,你的文件夹结构看起来不错。特别是如果它对你有用的话。当我浏览它时,我可以很好地了解每个包的作用。唯一让我不是 100% 确定的是 tmp 文件夹,因为它可能代表多种含义。但我相信只要快速查看一下,就能解答我关于它的任何疑问。

这是典型的依赖注入(Dependency Injection)架构,结合了接口隔离控制反转原则。这种架构在Go社区中广泛使用,特别是通过构造函数注入依赖。

架构分析

// 1. 定义接口(抽象层)
type UserService interface {
    GetUser(id int) (*User, error)
    CreateUser(user *User) error
}

type UserRepository interface {
    FindByID(id int) (*User, error)
    Save(user *User) error
}

// 2. 实现具体类型(实现层)
type userServiceImpl struct {
    repo UserRepository
    db   *sql.DB
    cfg  *Config
}

// 3. 构造函数注入依赖
func NewUserService(repo UserRepository, db *sql.DB, cfg *Config) UserService {
    return &userServiceImpl{
        repo: repo,
        db:   db,
        cfg:  cfg,
    }
}

// 4. 实现接口方法
func (s *userServiceImpl) GetUser(id int) (*User, error) {
    // 使用注入的依赖
    return s.repo.FindByID(id)
}

// 5. 在main函数或初始化层组装依赖
func main() {
    db := initDatabase()
    cfg := loadConfig()
    repo := NewUserRepository(db)
    userService := NewUserService(repo, db, cfg)
    
    // 使用userService
}

关键特点

  1. 依赖注入:通过构造函数显式传入依赖
  2. 接口编程:依赖接口而非具体实现
  3. 单一职责:每个结构体只负责一个领域
  4. 可测试性:可以轻松mock依赖进行单元测试

测试示例

// 单元测试时可以mock依赖
type mockRepository struct {
    mock.Mock
}

func (m *mockRepository) FindByID(id int) (*User, error) {
    args := m.Called(id)
    return args.Get(0).(*User), args.Error(1)
}

func TestUserService_GetUser(t *testing.T) {
    mockRepo := new(mockRepository)
    expectedUser := &User{ID: 1, Name: "John"}
    
    mockRepo.On("FindByID", 1).Return(expectedUser, nil)
    
    service := NewUserService(mockRepo, nil, nil)
    user, err := service.GetUser(1)
    
    assert.NoError(t, err)
    assert.Equal(t, expectedUser, user)
    mockRepo.AssertExpectations(t)
}

这种架构在Go项目中非常常见,特别适合中大型项目,能够有效降低耦合度,提高代码的可测试性和可维护性。

回到顶部