从项目学习 Golang (3) - 包的外部接口与注释, 主进程常驻, 动态加载配置文件

抓取 Binance 的盘口价格 (3)

package 包的管理

  1. 包名一般情况和文件夹名相同.
  2. 相同包下, 不同文件的调用无需使用任何其他前缀等操作.
  3. 包外部访问使用 包名.方法名
  4. 只有命名为首字母大写的方法或 struct, 才能被包外部调用, 类似 public 方法.
  5. public 方法必须有注释, 注释格式为 // 方法名 实际注释内容

如何让主进程不退出

一般情况, 很多业务逻辑都使用了 go 协程进行, 主进程的作用变得好像只是拉起一些方法.

那么怎么让主进程常驻呢, 网上找了一下, 大致就是创造死循环或者读取一个不会有数据的 channel.

1
2
3
4
5
6
for {
// ...
}

var c = make(chan bool)
<-c

基于观察者模式的配置文件动态加载

基本思路

动态加载配置文件的思路大致有 2 个, 定时根据文件的最后修改日期判断(只存储一个上次修改时间戳), 或者定时直接重新读取文件内容(要存储整体文件内容或者单个存储逐一比较)

首先根据文件修改日期, 或者存储文件整体内容的方案比较类似, 实现起来相对简单. 劣势就是修改的内容可能只涉及某一部分, 但是全部内容都要进行更新. 涉及到长连接的要短线重连(即使改的不是和长连接相关的配置内容).

文件中的值单一存储, 这样在某个值变化时, 可以有针对性的重启某些业务.

参考文档: https://cloud.tencent.com/developer/article/1165960

代码实现

首先实现一个配置文件结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// BinanceConf 币安配置
type BinanceConf struct {
// 配置文件名
Filename string

Symbols []string `json:"symbols"`

// 本次解析的数据
Symbol string `json:"symbol"`

// 上次的数据
histSymbol string

// 观察者
observers []Observer
}

定时读取数据, 检查文件变更

1
2
3
4
5
6
7
8
9
10
11
12
func (bc *BinanceConf) Init(filename string) {
bc.Filename = filename

bc.ReadWatchConf()

go func() {
ticker := time.NewTicker(time.Second * 5)
for _ = range ticker.C {
bc.ReadWatchConf()
}
}()
}

读取文件判断变更细节

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// ReadWatchConf 读取监听盘口价格配置
func (bc *BinanceConf) ReadWatchConf() (err error) {
iniParser := utils.IniParser{}
if err := iniParser.Load(bc.Filename); err != nil {
fmt.Printf("try load config file[%s] error[%s]\n", bc.Filename, err.Error())
return err
}

// 重新从配置文件加载数据
bc.Symbol = iniParser.GetString("binance", "symbol")
bc.Symbols = strings.Split(bc.Symbol, ",")

// 配置文件有变更, 通知观察者
if bc.Symbol != bc.histSymbol {
fmt.Println("binance conf hot reload", bc)

for _, observer := range bc.observers {
observer.Notify(bc)
}
}

bc.histSymbol = bc.Symbol

return nil
}

定义观察者接口

1
2
3
4
// Observer 观察者模式接口
type Observer interface {
Notify(config *BinanceConf)
}

至此, 一个定时检查配置文件变更的观察者就完成了.

接下来在使用该配置文件的结构中定义观察者

1
2
3
4
5
6
7
type BinanceWatcher struct {}

// Notify 观察者模式调用的通知方法
func (bw *BinanceWatcher) Notify(binanceConf *BinanceConf) {
fmt.Println("Binance Config Chanaged", binanceConf)
// ... 做一些操作
}
Donate - Support to make this site better.
捐助 - 支持我让我做得更好.