面试题答案
一键面试1. 项目结构
假设项目结构如下:
project/
├── main.go
├── presentation/
│ └── presentation.go
├── businesslogic/
│ └── businesslogic.go
├── dataaccess/
│ └── dataaccess.go
2. 定义接口
在每个层定义接口,以便实现依赖注入。
- Data Access层接口:
// dataaccess/dataaccess.go
package dataaccess
type DataAccess interface {
GetData() string
}
- Business Logic层接口:
// businesslogic/businesslogic.go
package businesslogic
type BusinessLogic interface {
ProcessData() string
}
- Presentation层接口:
// presentation/presentation.go
package presentation
type Presentation interface {
DisplayData() string
}
3. 实现各层具体逻辑
- Data Access层实现:
// dataaccess/dataaccess.go
package dataaccess
type DataAccessorImpl struct{}
func (d *DataAccessorImpl) GetData() string {
return "原始数据"
}
- Business Logic层实现:
// businesslogic/businesslogic.go
package businesslogic
import "project/dataaccess"
type BusinessLogicImpl struct {
da dataaccess.DataAccess
}
func NewBusinessLogic(da dataaccess.DataAccess) *BusinessLogicImpl {
return &BusinessLogicImpl{da: da}
}
func (b *BusinessLogicImpl) ProcessData() string {
data := b.da.GetData()
// 处理数据
return "处理后的 " + data
}
- Presentation层实现:
// presentation/presentation.go
package presentation
import "project/businesslogic"
type PresentationImpl struct {
bl businesslogic.BusinessLogic
}
func NewPresentation(bl businesslogic.BusinessLogic) *PresentationImpl {
return &PresentationImpl{bl: bl}
}
func (p *PresentationImpl) DisplayData() string {
data := p.bl.ProcessData()
return "展示: " + data
}
4. 使用Go inject库进行依赖注入
首先安装go - get github.com/go - inject/inject
。
- 主函数中使用依赖注入:
// main.go
package main
import (
"fmt"
"github.com/go - inject/inject"
"project/dataaccess"
"project/businesslogic"
"project/presentation"
)
func main() {
var injector = inject.New()
// 注册DataAccess实现
injector.Map(&dataaccess.DataAccessorImpl{})
// 注册BusinessLogic实现,依赖DataAccess
var bl businesslogic.BusinessLogic
injector.MapToProvider(func(da dataaccess.DataAccess) businesslogic.BusinessLogic {
return businesslogic.NewBusinessLogic(da)
}, &bl)
// 注册Presentation实现,依赖BusinessLogic
var p presentation.Presentation
injector.MapToProvider(func(bl businesslogic.BusinessLogic) presentation.Presentation {
return presentation.NewPresentation(bl)
}, &p)
// 获取Presentation实例
injector.Invoke(func(p presentation.Presentation) {
result := p.DisplayData()
fmt.Println(result)
})
}
简要说明
- 接口定义:通过定义各层接口,使得不同层之间的依赖关系更加清晰,也方便进行单元测试和替换具体实现。
- 具体实现:每个层的具体实现结构体都通过接收依赖层的接口来进行初始化,例如
BusinessLogicImpl
接收DataAccess
接口,PresentationImpl
接收BusinessLogic
接口。 - Go inject库使用:使用
inject.New()
创建注入器,通过injector.Map
注册底层依赖(如DataAccessorImpl
),通过injector.MapToProvider
注册依赖关系并生成上层实例(如BusinessLogic
和Presentation
),最后通过injector.Invoke
获取并调用最终需要的实例方法。这样就实现了各层之间优雅的依赖注入,提高了代码的可测试性和可维护性。