Golang图数据结构 - 如何将访问方法作为参数传递?

Golang图数据结构 - 如何将访问方法作为参数传递? 我正在实现一个树结构。它由"Graph"结构体和"Node"结构体定义。

现在我想实现访问方法。具体来说,我想编写一个算法来访问每个节点(非常简单),并为每个节点调用visitNode()方法。这个方法将对每个节点都被调用。

我希望这个visitMethod作为参数传递给我的访问函数。访问函数遍历每个节点n,并调用visitMethod(n)。

func (g * Graph) visit( Visit func(*Node))    

<- 这是我的访问方法应该接收另一个方法作为参数的正确方式吗?

2 回复

引用 JOhn_Stuart:

func (g * Graph) visit( Visit func(*Node))

是的,就是这个 Go Playground - Go编程语言

package main

import (
	"fmt"
)

type Node struct {
	value interface{}
}

// 一个非常扁平的图 :)
type Graph struct {
	children []*Node
}

func (g * Graph) Visit(visit func(*Node)) {
	for _, n := range g.children {
		visit(n)
	}
}

func printNode(n *Node) {
	fmt.Println(n.value)
}	

func main() {
	g := Graph{}
	g.children = []*Node{&Node{value: "I'm a node"}, &Node{value: "I'm a another node"}}
	
	// 匿名函数
	g.Visit(func(n *Node) { fmt.Println(n.value) })
	
	// 命名函数
	g.Visit(printNode)
}

更多关于Golang图数据结构 - 如何将访问方法作为参数传递?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


是的,你的方法签名是正确的。在Go语言中,函数是一等公民,可以作为参数传递。你定义的visit方法接收一个函数类型参数Visit,该函数接受*Node作为参数且无返回值。

下面是一个完整的示例,展示如何实现和使用这种模式:

package main

import "fmt"

type Node struct {
    ID    int
    Value string
}

type Graph struct {
    Nodes []*Node
}

// 定义visit方法,接收函数作为参数
func (g *Graph) visit(visitFunc func(*Node)) {
    for _, node := range g.Nodes {
        visitFunc(node)
    }
}

func main() {
    // 创建图结构
    graph := &Graph{
        Nodes: []*Node{
            {ID: 1, Value: "Node 1"},
            {ID: 2, Value: "Node 2"},
            {ID: 3, Value: "Node 3"},
        },
    }
    
    // 定义不同的访问函数
    
    // 简单的打印函数
    printNode := func(n *Node) {
        fmt.Printf("Visiting node: ID=%d, Value=%s\n", n.ID, n.Value)
    }
    
    // 修改节点值的函数
    modifyNode := func(n *Node) {
        n.Value = fmt.Sprintf("Modified %s", n.Value)
    }
    
    // 统计节点数量的函数
    nodeCount := 0
    countNodes := func(n *Node) {
        nodeCount++
    }
    
    // 使用不同的访问函数
    fmt.Println("Printing nodes:")
    graph.visit(printNode)
    
    fmt.Println("\nModifying nodes:")
    graph.visit(modifyNode)
    graph.visit(printNode)
    
    fmt.Println("\nCounting nodes:")
    graph.visit(countNodes)
    fmt.Printf("Total nodes: %d\n", nodeCount)
}

输出结果:

Printing nodes:
Visiting node: ID=1, Value=Node 1
Visiting node: ID=2, Value=Node 2
Visiting node: ID=3, Value=Node 3

Modifying nodes:
Visiting node: ID=1, Value=Modified Node 1
Visiting node: ID=2, Value=Modified Node 2
Visiting node: ID=3, Value=Modified Node 3

Counting nodes:
Total nodes: 3

你还可以定义命名的函数类型来增强代码的可读性:

// 定义函数类型
type VisitFunc func(*Node)

// 使用方法签名更清晰
func (g *Graph) visit(visitFunc VisitFunc) {
    for _, node := range g.Nodes {
        visitFunc(node)
    }
}

这种模式在Go中很常见,允许你在不修改遍历算法的情况下,灵活地定义不同的节点处理逻辑。

回到顶部