跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • Golang map 全局变量使用问题,请各位大佬留步一观。
未分類
4 4 月 2020

Golang map 全局变量使用问题,请各位大佬留步一观。

Golang map 全局变量使用问题,请各位大佬留步一观。

資深大佬 : PEIENYKYK 35

各位大佬大家好,还是小弟我,这次开发遇到了一个挺坑的问题
首先说一下需求,我要完成一个任务的开始停止,对,就是这么简单。
小弟首先定义了一个全局的 map 变量去存储 job 的信息

//SyncJob 任务详情 type SyncJob struct {  ID     string  Ctx    context.Context  Cancel context.CancelFunc }  //Job 单个同步任务 var Job = make(map[string]interface{})  //JobWork job 列表 var JobWork = make(map[string][]map[string]interface{}) 

然后我定义了一个 startwork 和 stopwork,

//SyncStart 任务开始 func SyncStart(id string) (msg string, err error) {  var job SyncJob  ctx, cancel := context.WithCancel(context.Background())     go do work(id)  job.ID = id  job.Ctx = ctx  job.Cancel = cancel  Job[id] = job  JobWork["job"] = append(JobWork["job"], Job)  return "Start work success", nil } //SyncStop 任务结束 func SyncStop(id string) (msg string, err error) {  for _, i := range JobWork["job"] {   jobss := i[id]   op, _ := jobss.(SyncJob)   defer op.Cancel()  }  return "Stop work success", nil } 

我尝试了一下这种写法

infiapi.SyncStart("123456") time.Sleep(time.Second * 10) infiapi.SyncStop("123456") 

这样是可以停止任务的。 但是!小弟写了一个 web server, 想在 web server 中停止它

func StartSyncwork(w http.ResponseWriter, r *http.Request) {  r.ParseForm()       //解析参数,默认是不会解析的  fmt.Println(r.Form) //这些信息是输出到服务器端的打印信息  id := r.Form["uid"]  infiapi.SyncStart(string(id[0])) }  func StopSyncWork(w http.ResponseWriter, r *http.Request) {  r.ParseForm()       //解析参数,默认是不会解析的  fmt.Println(r.Form) //这些信息是输出到服务器端的打印信息  id := r.Form["uid"]  infiapi.SyncStop(string(id[0])) } ........ http.HandleFunc("/start", StartSyncwork) //设置访问的路由 http.HandleFunc("/stop", StopSyncWork) 

这样调用开启可以,但是 stop 无法停止,是 map 作用域的问题么?这样该如何解决呢??拜谢!

大佬有話說 (12)

  • 資深大佬 : OakScript

    net/http 本质是多 goroutine 模型,golang 的 map 并发读写会 panic…

  • 主 資深大佬 : PEIENYKYK

    @OakScript 我试下加锁,感恩老哥

  • 資深大佬 : songjiaxin2008

    首先记得加个锁… 不然会有竞争读写问题
    可以用`sync.Map`

    和作用域无关。
    `SyncStop`为什么要用`defer`呢 直接`op.Cancel()` 就可以了
    另外你这个多层套娃看的有点晕啊。。。搞个 repo 可以帮你看下

  • 資深大佬 : bobuick

    很久没写 golang 了,defer 这样在 for 里面用,疑似有坑。

  • 資深大佬 : songjiaxin2008

    for 里面调 defer 有泄漏的可能

  • 資深大佬 : OakScript

    搞个临时 repo 或者搞个 golang playground 出来吧,这样大家好帮你调试

  • 主 資深大佬 : PEIENYKYK

    @OakScript 谢谢老哥,问题已经解决,加了锁,优化了一下代码,感恩感恩!谢谢您!

  • 主 資深大佬 : PEIENYKYK

    @songjiaxin2008 问题已经解决,加了锁,优化了一下代码,感恩感恩!谢谢您!

  • 資深大佬 : beidounanxizi

    把 map 作为一个 channel 穿来穿去 可解忧

  • 資深大佬 : useben

    1 、for 里面不要 defer, 会有泄露问题
    2 、任务调度器一般不这样做的。起一个调度 goroutine 作为调度器,任务队列 chan,每个任务 go 一个协程来执行,并且创建一个 stopChan 来等待 stop 事件停止任务。然后通过 chan 或者队列的方式来投递任务和监听 chan 来消费任务。接口 start 创建任务和扔进 chan 。stop 接口发送 stop 事件到对应 stopChan,达到停止任务的目的

  • 資深大佬 : wnanbei

    @useben 现在 1.14 里还会有 for 里面 defer 会泄露的问题吗?

  • 資深大佬 : fighterlyt

    @wnanbei 一看就是不知道为什么会泄露

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具