Golang中如何在另一个函数调用里遍历slice
Golang中如何在另一个函数调用里遍历slice
大家好,我是Go语言新手,写了下面这个函数,但修改没有生效。我知道这是因为paths是按值传递的,但当我尝试按引用传递时,又无法遍历那个切片。我该怎么做呢?
func addNodeIdsToPaths(paths [][]node.Node) {
for _, path := range paths {
for _, node := range path {
ndId = funcToGetNodeId(node)
// 下面这个修改应该在此函数作用域外生效
node.NodeId = ndId
}
}
}
更多关于Golang中如何在另一个函数调用里遍历slice的实战教程也可以访问 https://www.itying.com/category-94-b0.html
6 回复
你也可以这样做:
func addNodeIdsToPaths(paths [][]node.Node) {
for _, path := range paths {
for i := range path {
node := &path[i]
ndId = funcToGetNodeId(node)
// 下面的更改应该在此函数作用域之外反映出来
node.NodeId = ndId
}
}
}
skillian:
node := &path[i]
ndId = funcToGetNodeId(node)
根据问题描述:
farhan787:
func addNodeIdsToPaths(paths [][]node.Node) {
for _, path := range paths {
for _, node := range path {
ndId = funcToGetNodeId(node)
// 下面的更改应该在此函数作用域之外生效
node.NodeId = ndId
}
}
}
这似乎意味着
func funcToGetNodeId(node node.Node) int
这可能会将您的解决方案更改为
node := &path[i]
ndId := funcToGetNodeId(*node)
由于您没有发布代码的关键部分,因此很难给出精确的解答。
您正在更新本地的 range 迭代变量 node。
node.NodeId = ndId
您还需要更新切片元素。
node.NodeId = ndId
paths[i][j] = node
类似这样:
for i, path := range paths {
for j, node := range path {
ndId := funcToGetNodeId(node)
// 下面的更改应该反映在此函数作用域之外
node.NodeId = ndId
paths[i][j] = node
}
}
Range
for循环的range形式用于遍历切片或映射。在遍历切片时,每次迭代会返回两个值。第一个是索引,第二个是该索引处元素的副本。
For 语句
带有
range子句的 For 语句带有 “range” 子句的 “for” 语句会遍历切片的所有条目。对于每个条目,如果存在相应的迭代变量,它会将迭代值分配给这些变量,然后执行代码块。
在Go语言中,切片本身就是一个引用类型(包含指向底层数组的指针),但切片中的结构体元素是按值传递的。你的代码需要直接修改切片中的元素,而不是副本。以下是修正后的代码:
func addNodeIdsToPaths(paths [][]node.Node) {
for i := range paths {
for j := range paths[i] {
ndId := funcToGetNodeId(paths[i][j])
// 直接修改切片中的元素
paths[i][j].NodeId = ndId
}
}
}
关键点:
- 使用索引
i和j直接访问切片元素 range paths返回的是切片副本,但paths[i]和paths[i][j]允许直接修改原始数据- 切片是引用类型,所以函数外部的修改会生效
示例验证:
package main
import "fmt"
type Node struct {
NodeId int
Value string
}
func funcToGetNodeId(n Node) int {
return len(n.Value) * 10
}
func addNodeIdsToPaths(paths [][]Node) {
for i := range paths {
for j := range paths[i] {
ndId := funcToGetNodeId(paths[i][j])
paths[i][j].NodeId = ndId
}
}
}
func main() {
paths := [][]Node{
{{Value: "a"}, {Value: "ab"}},
{{Value: "abc"}, {Value: "abcd"}},
}
fmt.Println("修改前:", paths)
addNodeIdsToPaths(paths)
fmt.Println("修改后:", paths)
}
输出:
修改前: [{{0 a} {0 ab}} {{0 abc} {0 abcd}}]
修改后: [{{10 a} {20 ab}} {{30 abc} {40 abcd}}]
这样修改会直接作用于原始切片,因为:
- 外层切片
paths是引用类型 - 内层切片
paths[i]也是引用类型 - 通过索引直接修改结构体字段会改变原始数据

