问题描述
我正在尝试编写一个 CLI 工具来查找启用了 go 模块的项目中最长依赖链的长度。为此,我获取 go mod graph
的输出并从中删除依赖版本,然后以 map[string][]string
的形式创建图形的邻接列表表示。代码如下:
depGraph := make(map[string][]string)
scanner := bufio.NewScanner(strings.NewReader(goModGraphOutputString))
// deps will store all the dependencies
// since can't do slice.contains so better to use map
deps := make(map[string]bool)
mainModule := "notset"
for scanner.Scan() {
line := scanner.Text()
words := strings.Fields(line)
// remove versions
words[0] = (strings.Split(words[0],"@"))[0]
words[1] = (strings.Split(words[1],"@"))[0]
if mainModule == "notset" {
mainModule = words[0]
}
deps[words[0]] = true
deps[words[1]] = true
// we don't want to add the same dep again
if !contains(depGraph[words[0]],words[1]) {
depGraph[words[0]] = append(depGraph[words[0]],words[1])
}
}
之后为了得到最长链的长度,我使用动态编程运行了一个 DFS:
dp := make(map[string]int)
// visited array will make sure we don't have infinite recursion
visited := make(map[string]bool)
// values not in map will have their respective 0 value by default
// so need to worry about terminal nodes
for k := range deps {
dp[k] = 0
visited[k] = false
}
for k := range deps {
if visited[k] == false {
dfs(k,depGraph,dp,visited)
}
}
// perform depth first search from current dependency
func dfs(k string,graph map[string][]string,dp map[string]int,visited map[string]bool) {
visited[k] = true
// for terminal deps we won't go into this for loop
// and so vis for them would be true and dp would be 0
// since in maps non existent keys have 0 value by default
for _,u := range graph[k] {
if visited[u] == false {
dfs(u,graph,visited,longestPath)
}
dp[k] = max(dp[k],1+dp[u])
}
}
然后最长的路径就是值 dp[mainModule]
。但是当在有周期的大型项目上运行这个时,我每次都会得到不同的答案。这个算法有错误吗?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)