TL;博士 我有一个由Node结构定义的任意有向图。 我现在希望能够提供一种方法来编写遍历此图的函数,并使用特定于该函数的元数据“标记”每个节点。
例如,考虑一个计算节点数的函数:
type Node struct {
Nexts []*Node
}
func CountNodes(root *Node) int {
m := make(map[*Node]bool)
return countNodesHelper(root, m)
}
func countNodesHelper(root *Node, m map[*Node]bool) int {
_, seen := m[root]
if seen {
return 0
}
m[root] = true
c := 1
for _, child := range root.Nexts {
c += countNodesHelper(child, m)
}
return c
}
func main() {
n1 := &Node{make([]*Node, 0, 1)}
n2 := &Node{[]*Node{n1}}
n1.Nexts = append(n1.Nexts, n2)
fmt.Println(CountNodes(n1))
}
如果我在struct中添加了“seen”标记,我可以重写它:
type NodeWithTag struct {
Nexts []*NodeWithTag
Seen bool
}
func CountNodesWithTag(root *NodeWithTag) int {
if root.Seen {
return 0
}
root.Seen = true
c := 1
for _, child := range root.Nexts {
c += CountNodesWithTag(child)
}
return c
}
func main() {
n1 := &NodeWithTag{make([]*NodeWithTag, 0, 1), false}
n2 := &NodeWithTag{[]*NodeWithTag{n1}, false}
n1.Nexts = append(n1.Nexts, n2)
fmt.Println(CountNodesWithTag(n1))
}
但是Seen标签对于树上的DFS是不够的,我也想找到向后的边缘(你需要数到2 - 从未见过,见过,第二次看到一个路径)。所以,我想要一些方法来允许函数的实现使用它自己的类型来标记结构。大致等同于:
type Node struct {
...
// Not valid golang
void* tag
}
但更安全的是void * - 该函数应该能够静态验证标记是否是它所期望的当前类型。有没有办法做到这一点/另一种方法。
我想将标记与Node(而不是标记的单独地图/存储)相关联的原因是为了允许使用这些标记的函数的简单并行化,将节点分配到不同的goroutine。在第一种方法中,地图必须在goroutine之间共享,这很快就会成为瓶颈,因为它需要同步访问。
答案 0 :(得分:1)
如果您需要支持任意数据类型,则需要使用空接口:
type NodeWithTag struct {
Nexts []*NodeWithTag
Tag interface{}
}
您可以为Tag
字段指定任何值。如果要验证该值是否为某种类型,例如MyType
,则可以使用类型断言:
myVal, ok := node.Tag.(MyType)
如果值属于该类型,则ok
将为true,myVal
将包含输入的值。