gpt4 book ai didi

go - 将 slice 作为函数参数传递,并修改原始 slice

转载 作者:IT王子 更新时间:2023-10-29 01:04:24 24 4
gpt4 key购买 nike

我知道在 Go 中一切都是按值传递的,这意味着如果我给一个函数一个 slice 并且该函数使用内置的 append 函数附加到 slice ,那么原始 slice 将没有附加在函数范围内的值。

例如:

nums := []int{1, 2, 3}

func addToNumbs(nums []int) []int {
nums = append(nums, 4)
fmt.Println(nums) // []int{1, 2, 3, 4}
}

fmt.Println(nums) // []int{1, 2, 3}

这对我来说是个问题,因为我正在尝试对累积的 slice 进行递归,基本上是一个 reduce 类型的函数,除了 reducer 调用自身。

这是一个例子:

func Validate(obj Validatable) ([]ValidationMessage, error) {
messages := make([]ValidationMessage, 0)

if err := validate(obj, messages); err != nil {
return messages, err
}

return messages, nil
}

func validate(obj Validatable, accumulator []ValidationMessage) error {
// If something is true, recurse
if something {
if err := validate(obj, accumulator); err != nil {
return err
}
}

// Append to the accumulator passed in
accumulator = append(accumulator, message)

return nil
}

上面的代码给出了与第一个示例相同的错误,因为 accumulator 没有获得所有附加值,因为它们只存在于函数的范围内。

为了解决这个问题,我将一个指针结构传递给函数,该结构包含累加器。该解决方案效果很好。

我的问题是,是否有更好的方法来执行此操作,我的方法是否符合 Go 的惯用方法?

更新的解决方案(感谢 icza):

我只是在递归函数中返回 slice 。这么狠的脸,早该想到的。

func Validate(obj Validatable) ([]ValidationMessage, error) {
messages := make([]ValidationMessage, 0)
return validate(obj, messages)
}

func validate(obj Validatable, messages []ValidationMessage) ([]ValidationMessage, error) {
err := v.Struct(obj)

if _, ok := err.(*validator.InvalidValidationError); ok {
return []ValidationMessage{}, errors.New(err.Error())
}

if _, ok := err.(validator.ValidationErrors); ok {
messageMap := obj.Validate()

for _, err := range err.(validator.ValidationErrors) {
f := err.StructField()
t := err.Tag()

if v, ok := err.Value().(Validatable); ok {
return validate(v, messages)
} else if _, ok := messageMap[f]; ok {
if _, ok := messageMap[f][t]; ok {
messages = append(messages, ValidationMessage(messageMap[f][t]))
}
}
}
}

return messages, nil
}

最佳答案

如果你想将一个 slice 作为参数传递给一个函数,并让该函数修改原始 slice ,那么你必须传递一个指向该 slice 的指针:

func myAppend(list *[]string, value string) {
*list = append(*list, value)
}

我不知道 Go 编译器对此是天真还是聪明;性能留作评论区练习。

对于那里的初级编码人员,请注意提供的代码没有错误检查。例如,如果 listnil,此代码将出现 panic。

关于go - 将 slice 作为函数参数传递,并修改原始 slice ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49428716/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com