首页 > 解决方案 > 如何更新另一个结构中的结构切片的属性?

问题描述

我有一个Jobs结构,其中包含一个类型的结构切片Job。我想遍历每个Job并“执行”它们,更新它们在过程中的状态。

代码如下:

package main

import (
    "fmt"
    "strconv"
)

type Job struct {
    id     int
    status string
}

type Jobs struct {
    jobs []Job
}

func main() {
    jobs := Jobs{}

    job := Job{id: 1, status: "pending"}

    jobs.load(job)

    job2 := Job{id: 2, status: "pending"}

    jobs.load(job2)

    fmt.Println(jobs) // jobs should be pending

    jobs.execute()

    fmt.Println(jobs) // jobs should be executing
}

func (j *Jobs) load(job Job) {
    j.jobs = append(j.jobs, job)
}

func (j *Jobs) execute() {
    for _, job := range j.jobs {
        if err := job.execute(); err != nil {
            id := strconv.Itoa(job.id)
            fmt.Println("error occurred when executing job #" + id)
        }
    }
}

func (j *Job) execute() error {
    j.status = "executing"
    fmt.Println("Executing job")

    // return errors.New("error when executing job")

    return nil
}

运行时输出:

{[{1 pending} {2 pending}]}
Executing job
Executing job
{[{1 pending} {2 pending}]}

预期输出:

{[{1 pending} {2 pending}]}
Executing job
Executing job
{[{1 executing} {2 executing}]}

我想我在某处丢失了一个指针,但我就是无法得到它。

标签: gopointersstruct

解决方案


当你这样做时:

for _, job := range j.jobs {

在循环内部,job是一个局部变量,其中包含切片中元素的副本。因此,当您修改它时,它会修改副本,而不是切片内的值。为了解决这个问题,您需要获取指向切片元素本身的指针 ( &j.jobs[i]),或者制作jobs一个指针切片而不是值切片。后者对于阅读它的其他人可能更清楚,因为看到一片指针,他们会期望这些值会被针对它们运行的​​函数更新。

Go 中还有一个通用习惯用法,即当类型的方法使用指针接收器时,这意味着使用该类型的“正常”方式是使用指针。在这里,您定义了一个带有指针接收器的类型,但您使用的是值,这有点不寻常(但肯定不是闻所未闻)。


推荐阅读