【问题标题】:How to return changed values of slice from function? [duplicate]如何从函数返回切片的更改值? [复制]
【发布时间】:2017-07-14 12:27:18
【问题描述】:

我是新来的,如果这是一个微不足道的问题,请原谅我。我想遍历一段帖子并增加每个帖子的Views 的值:

    func incrementViews(posts []model.Post) []model.Post {
        for _, v := range posts { 
            v.Views++
            fmt.Println(v.Views) //Views incremented by 1
        }
        return posts
    }

    incrementViews(posts) //Views not changed

打印的值发生了变化,但是当我调用incrementViews(posts) 时,返回的值没有改变。

我试图通过使用&* 来解决这个问题,但可能因为我来自Python 背景并且无法通过指针和值移动变量而无法做到这一点。

【问题讨论】:

    标签: go slice


    【解决方案1】:

    问题中的代码是更新局部变量v。将切片更改为 *model.Post 或使用索引运算符更新切片中的值。前者需要对调用者进行更改。

    func incrementViews(posts []*model.Post) []*model.Post {
        for _, v := range posts { 
            v.Views++
        }
        return posts
    }
    
    func incrementViews(posts []model.Post) []model.Post {
        for i := range posts { 
            posts[i].Views++
        }
        return posts
    }
    

    编辑:

    这两种方法都有效,请参见此处:https://play.golang.org/p/90BNOFYaKL

    【讨论】:

    • 第一种方法报错:cannot use posts (type []model.Post) as type []*model.Post in argument to incrementViews
    • @sahaj 然后我得到 2 个错误:cannot use posts (type []*model.Post) as type []model.Post in return argumentcannot use &posts (type *[]model.Post) as type []*model.Post in argument to incrementViews
    • @Karlom 我相信请对您的评论保持礼貌。刚刚添加了一个播放示例链接。
    • @Karlom 它是从for each 行上的main 函数调用的。请看一看。
    • @Karlom 我不确定你想说什么。方法incrementViews1incrementViews2 将切片作为输入并更改值,然后在主函数上返回给调用者。我只是迭代结果而不是存储在变量中。但结果会一样。您可以修改并运行它。你会看到的。
    【解决方案2】:

    range 表达式返回切片元素的副本。因此,在迭代过程中要修改切片元素时要非常小心。

    切片或数组上的range 表达式返回第一个参数作为索引,第二个参数作为该索引处元素的副本。在您的示例中,您正在修改 range 返回的副本,因此未在原始切片元素中进行修改。

    您需要更改的是,使用[index] 引用切片名称,以便您实际引用切片中的原始元素,从而可以修改原始切片元素。请参阅 jeevatkm 给出的工作示例中的second approach

    另一种选择是使用地址切片,在这种情况下,您可以引用范围返回的值,因为即使它是副本,它也是地址位置的副本,它仍然指向原始元素。请参阅 jeevatkm 给出的工作示例中的第一种方法。

    【讨论】:

    • 讲得好。但是,这如何转化为工作代码?
    • @shaj 您刚刚在其他答案 cmets 中复制了操场,这与我的情况无关,我不会遍历 incrementViews 函数来获取切片内结构的值已更改。
    • 听不懂,你想说什么?您能否将您的示例代码放在操场上并解释确切的疑问?
    • 您是否打算这样做:play.golang.org/p/HICoue8Qp6。如本例所示,您可以创建一个newPosts 切片来保存更改的元素,然后将其返回。
    • 是的,这是想要实现的,但如果可能的话,不要在函数内部创建新切片。
    猜你喜欢
    • 2020-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-07
    • 2016-01-14
    相关资源
    最近更新 更多