dp152153
2015-08-13 08:36
浏览 223
已采纳

如何在goroutine闭包内更改外部变量的值

func (this *l) PostUpload(ctx *Context) {

    //ctx.Response.Status = 500

    l, err := models.NewL(this.Config)
    go func() {
        err = l.Save(file) 
        if err != nil {
            ctx.Response.Status = 500
            ctx.Response.Body = err
        } else {
            ctx.Response.Status = 204
        }
    }()
}

How to change ctx.Response.Status value inside the goroutine closure?

图片转代码服务由CSDN问答提供 功能建议

  func(this * l)PostUpload(ctx * Context){
 
 // ctx。  Response.Status = 500 
 
l,err:= models.NewL(this.Config)
 go func(){
 err = l.Save(file)
 if err!= nil {
 ctx。  Response.Status = 500 
 ctx.Response.Body = err 
} else {
 ctx.Response.Status = 204 
} 
}()
} 
   \  n 
 

如何在goroutine闭包内更改 ctx.Response.Status 值?

  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • dqly83915 2015-08-13 09:19
    已采纳

    You have no guarantee to observe changes made to the value of a variable in another goroutine without synchronization. See The Go Memory Model for details.

    So if you want to change ctx.Response.Status in another goroutine, for this change to be guaranteed to be visible in the caller goroutine use synchronization.

    There are multiple synchronization primitives. You can use channels or the sync package.

    Using channels:

    ch := make(chan int)
    
    go func() {
        err = l.Save(file) 
        if err != nil {
            ctx.Response.Status = 500
            ctx.Response.Body = err
        } else {
            ctx.Response.Status = 204
        }
        ch <- 0 // Signal that ctx is updated
        // goroutine may do other works (not related to changing ctx)
    }()
    
    <- ch // Wait for the goroutine to finish updating ctx
    

    Using sync.WaitGroup:

    var wg sync.WaitGroup
    wg.Add(1)
    
    go func() {
        err = l.Save(file) 
        if err != nil {
            ctx.Response.Status = 500
            ctx.Response.Body = err
        } else {
            ctx.Response.Status = 204
        }
        wg.Done() // Signal that ctx is updated
        // goroutine may do other works (not related to changing ctx)
    }()
    
    wg.Wait() // Wait for the goroutine to finish updating ctx
    

    Using sync.Mutex:

    m := sync.Mutex{}
    m.Lock()
    
    go func() {
        err = l.Save(file) 
        if err != nil {
            ctx.Response.Status = 500
            ctx.Response.Body = err
        } else {
            ctx.Response.Status = 204
        }
        m.Unlock() // Signal that ctx is updated
        // goroutine may do other works (not related to changing ctx)
    }()
    
    m.Lock() // Wait for the goroutine to finish updating ctx
    

    Note:

    It is good practice to signal the completion (ctx update in your case) using defer so that if the started goroutine would end in some unexpected way (e.g. runtime panic), the caller goroutine would not get blocked forever. Note that however in this case the completion signal will only be sent at the end of the anonymous function (that's when deferred functions are executed).

    已采纳该答案
    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题