go 中的递归函数不存储更改

Recursive function in go is not storing changes

提问人:7uper 提问时间:8/17/2022 更新时间:8/18/2022 访问量:274

问:

//Recursively set ExternalID for all Parts, PartUse, Components in Component struct
func (svc *ProductManagementClient) setExternalID(input *[]Component) *[]Component {
    for _, component := range *input {
        if component.Components != nil {
            component.Components = svc.setExternalID(component.Components)
        }
        component.PartUse.ExternalID = component.PartUse.ID
        component.Part.ExternalID = component.Part.ID
        for _, occurrence := range component.Occurrences {
            occurrence.ExternalID = occurrence.ID
        }
        component.ExternalID = "PartID:" + component.Part.ID + ",PartUseID:" + component.PartUse.ID
        zap.S().Debug("ExternalID for component:", component.ExternalID)
    }
    return input
}

在此函数中,我尝试为这些结构设置 ExternalID 字段,并从另一个函数调用它。代码片段如下:

// Set externalID for each Part, PartUse and Component
for _, component := range retBOM.Components {
    component.Components = svc.setExternalID(component.Components)
}

这些更改没有被持久化,我无法说出原因。当我查看结果时,ExternalID 字段仍然为空。我正在编写一个递归函数,因为 Component 字段是嵌套的。我该如何解决这个问题?

我试图通过引用,但显然这在 Golang 中是不允许的。

Go 递归 传递

评论

4赞 mkopriva 8/17/2022
“我无法说出原因” -- 迭代变量是要迭代的切片中元素的副本。使用指针(即 )或重新分配切片中的元素(即 )。componentinput[]*Compontent(*input)[i] = component
4赞 mkopriva 8/17/2022
请注意,使用指向切片的指针并不常见,尤其是当指针是输入输出时。J.F.公司 作为不修改 slice-header 的函数的参数是不寻常的。*[]Component
0赞 mkopriva 8/17/2022
go.dev/play/p/2Abfgkc8SwQ

答:

0赞 iddqdeika 8/17/2022 #1

这是因为在循环中,您正在修改组件的副本。在迭代结束时,您必须将其替换为

for i, component := range *input {
    if component.Components != nil {
        component.Components = svc.setExternalID(component.Components)
    }
    component.PartUse.ExternalID = component.PartUse.ID
    component.Part.ExternalID = component.Part.ID
    for _, occurrence := range component.Occurrences {
        occurrence.ExternalID = occurrence.ID
    }
    component.ExternalID = "PartID:" + component.Part.ID + ",PartUseID:" + component.PartUse.ID
    zap.S().Debug("ExternalID for component:", component.ExternalID)
    // replace current state by new one
    *input[i] = component
}

或使用 []*Component / *[]*Component 代替 *[]Component

0赞 Sebry 8/18/2022 #2

这里有一个密切相关的问题

但正如许多人指出的那样,您传递的是组件的副本,但传递的是切片的地址。

因此,处理此问题的最快方法是使用 通俗易懂的指针组件[]*Component