【问题标题】:How can I update the properties of a slice of structs within another struct?如何更新另一个结构中的结构切片的属性?
【发布时间】:2023-03-18 19:14:01
【问题描述】:

我有一个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}]}

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

【问题讨论】:

    标签: go pointers struct


    【解决方案1】:

    当你这样做时:

    for _, job := range j.jobs {
    

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

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

    【讨论】:

      【解决方案2】:

      只需更改作业的存储方式:

      type Jobs struct {
          jobs []*Job
      }
      

      然后在代码中到处使用指针:

      func (j *Jobs) load(job *Job) {
          j.jobs = append(j.jobs, job)
      }
      
      
      jobs := Jobs{}
      
      job := &Job{id: 1, status: "pending"}
      jobs.load(job)
      
      job2 := &Job{id: 2, status: "pending"}
      jobs.load(job2)
      

      【讨论】:

        猜你喜欢
        • 2017-12-18
        • 1970-01-01
        • 2019-04-12
        • 1970-01-01
        • 2014-08-24
        • 1970-01-01
        • 2020-09-02
        • 1970-01-01
        • 2015-02-21
        相关资源
        最近更新 更多