面试题答案
一键面试实现思路
- 初始化顺序管理:
- 定义依赖关系图:通过分析被注入对象之间的依赖关系,构建一个有向无环图(DAG)。在Go中,可以使用结构体和链表等数据结构来表示。例如,一个对象A依赖对象B和C,那么B和C应该在A之前初始化。
- 拓扑排序:对依赖关系图进行拓扑排序,以确定正确的初始化顺序。可以使用Kahn算法来实现拓扑排序。该算法从入度为0的节点开始,依次将其移除并更新其他节点的入度,直到所有节点都被处理。
- 销毁顺序管理:
- 记录初始化顺序:在初始化过程中,记录对象的初始化顺序。可以使用一个切片来存储已初始化对象的引用。
- 逆序销毁:在应用程序关闭时,按照初始化顺序的逆序来销毁对象。这样可以确保依赖的对象先被销毁,避免出现悬空引用等问题。
- 资源管理:
- 初始化函数:每个被注入对象应该有一个初始化函数,用于初始化其内部资源,如数据库连接、文件句柄等。
- 销毁函数:每个被注入对象也应该有一个销毁函数,用于释放其占用的资源。
关键代码结构
- 定义依赖对象和生命周期函数:
type Dependency struct {
Name string
Init func() error
Destroy func() error
}
- 构建依赖关系图:
type DependencyGraph struct {
Nodes map[string]*Dependency
Edges map[string][]string
}
func NewDependencyGraph() *DependencyGraph {
return &DependencyGraph{
Nodes: make(map[string]*Dependency),
Edges: make(map[string][]string),
}
}
func (g *DependencyGraph) AddNode(name string, dep *Dependency) {
g.Nodes[name] = dep
}
func (g *DependencyGraph) AddEdge(from, to string) {
g.Edges[from] = append(g.Edges[from], to)
}
- 拓扑排序:
func TopologicalSort(graph *DependencyGraph) ([]*Dependency, error) {
inDegree := make(map[string]int)
for _, edges := range graph.Edges {
for _, to := range edges {
inDegree[to]++
}
}
queue := []string{}
for name, dep := range graph.Nodes {
if inDegree[name] == 0 {
queue = append(queue, name)
}
}
result := []*Dependency{}
for len(queue) > 0 {
current := queue[0]
queue = queue[1:]
result = append(result, graph.Nodes[current])
for _, to := range graph.Edges[current] {
inDegree[to]--
if inDegree[to] == 0 {
queue = append(queue, to)
}
}
}
if len(result) != len(graph.Nodes) {
return nil, fmt.Errorf("dependency cycle detected")
}
return result, nil
}
- 初始化和销毁对象:
func Initialize(deps []*Dependency) error {
for _, dep := range deps {
if dep.Init != nil {
if err := dep.Init(); err != nil {
return err
}
}
}
return nil
}
func Destroy(deps []*Dependency) error {
for i := len(deps) - 1; i >= 0; i-- {
if deps[i].Destroy != nil {
if err := deps[i].Destroy(); err != nil {
return err
}
}
}
return nil
}
- 应用程序启动和关闭:
func main() {
graph := NewDependencyGraph()
depA := &Dependency{Name: "A", Init: func() error { fmt.Println("Initializing A"); return nil }, Destroy: func() error { fmt.Println("Destroying A"); return nil }}
depB := &Dependency{Name: "B", Init: func() error { fmt.Println("Initializing B"); return nil }, Destroy: func() error { fmt.Println("Destroying B"); return nil }}
depC := &Dependency{Name: "C", Init: func() error { fmt.Println("Initializing C"); return nil }, Destroy: func() error { fmt.Println("Destroying C"); return nil }}
graph.AddNode("A", depA)
graph.AddNode("B", depB)
graph.AddNode("C", depC)
graph.AddEdge("B", "A")
graph.AddEdge("C", "A")
deps, err := TopologicalSort(graph)
if err != nil {
fmt.Println(err)
return
}
if err := Initialize(deps); err != nil {
fmt.Println(err)
return
}
defer func() {
if err := Destroy(deps); err != nil {
fmt.Println(err)
}
}()
// 应用程序逻辑
}
以上代码通过构建依赖关系图、拓扑排序来管理对象的初始化顺序,并在初始化和销毁时调用相应的生命周期函数,从而有效管理被注入对象的生命周期。