登录
首页 >  Golang >  Go问答

在包的 `init()` 函数中包含无限 for 循环——明智之举还是不明智之举?

来源:stackoverflow

时间:2024-03-23 21:00:37 404浏览 收藏

在 Go 包的 `init()` 函数中包含无限 for 循环是一个有争议的做法。有些人认为这是明智之举,因为它允许持续的后台处理,例如定期刷新数据或监控事件。然而,其他人则认为这是不明智的,因为它可能会导致长期可维护性问题,例如难以测试和推理。

问题内容

我想知道在包的 init() 函数中使用无限 for 循环是否是一个坏主意,或者是否应该避免这样做。

是否有人有任何知识或经验,如果可以这样做或应该避免这种情况?

你会在哪里使用它?

这可以用于例如提供来自外部源的一些信息的包,这些信息必须定期刷新(例如每天一次)。

我使用了如下类似的代码,但没有“看门狗”功能。这意味着 init() 刚刚启动了一个 go 例程,该例程将在后台运行,并在 tick 到达时运行更新过程。

不幸的是,这个更新机制在 aprox 之后停止工作。由于未知原因,3 个月了,但服务运行良好,只是使用“旧”数据。

简单示例实现

https://play.golang.org/p/k-gi1t9j4op 上的完整示例

package info

import (
  "log"
  "sync"
  "time"
)

var (
  data map[string]interface{}
  lock sync.RWMutex
)

func init() {
  // ticker channel
  ticker := time.NewTicker(1 * time.Second).C

  // "watchdog" loop
  for {
    log.Println("Starting Update Loop")
    var wg sync.WaitGroup
    wg.Add(1)

    // Start asyc update process.
    go func() {
      defer wg.Done() //notify wg when if process ends for whatever reason

      // Loop forever
      // Run when a tick is received from the `ticker` channel
      for {
        select {
        case <-ticker:
          log.Println("Update ticker received")
          err := update()
          if err != nil {
            log.Printf("ERROR: %v\n", err.Error())
          }
        }
      }
    }()

    wg.Wait()
  }
}

// internal update function that retrieves some information from some external system
func update() error {
  lock.Lock()
  defer lock.Unlock()
  log.Println("Update `data`")
  // retrieve information and update `data`
  return nil
}

// Public function to query data
func GetInformation(key string) interface{} {
  lock.RLock()
  defer lock.RUnlock()
  return data[key]
}

该代码可以正常工作并在单元测试中运行良好,并且也可以正常运行。 我想知道长期稳定性(一年或更长的正常运行时间)等等。


解决方案


它位于 goroutine 中,因此技术上没有问题,但直接在 init 中实现行为会使其非常难以使用,原因有两个:

  1. 很难测试,就像 main 很难测试一样。测试 init 是否调用另一个函数要容易得多,然后可以对其进行测试。
  2. 这很难推理。 “自动”发生的事情越多,对于使用该包的任何开发人员(包括未来的你)来说,它的意义就越小。 “好吧,我导入了这个包并使用了一个微小的函数,现在不知怎的,我的 CPU 使用率从 1% 上升到了 50%,我做错了什么”,这样的事情将会出现,需要更多的探索才能弄清楚。

TL;DR 不存在“长期稳定性”问题,但很可能存在长期可维护性问题。

文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《在包的 `init()` 函数中包含无限 for 循环——明智之举还是不明智之举?》文章吧,也可关注golang学习网公众号了解相关技术文章。

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>