从项目学习 Golang (2) - 接入 Binance 开源库, 写 Redis ZSet 数据, JSON 格式化操作, 代码换行问题

抓取 Binance 的盘口价格 (2)

接入 Binance 开源库

安装依赖 go get github.com/adshao/go-binance

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
26
27
28
29
30
31
import (
"fmt"
"time"
"github.com/adshao/go-binance"
)

func main() {
wsPartialDepthHandler := func(event *binance.WsPartialDepthEvent) {
timeStr := time.Now().Format("2006-01-02 15:04:05")
fmt.Println(timeStr, event)
}

errHandler := func(err error) {
fmt.Println(err)
}

doneC, stopC, err := binance.WsPartialDepthServe("BTCUSDT", "5", wsPartialDepthHandler, errHandler)
if err != nil {
fmt.Println(err)
return
}

// 向 stopC 写数据, 即可退出监听程序
go func() {
time.Sleep(5 * time.Second)
stopC <- struct{}{}
}()

// remove this if you do not want to be blocked here
<-doneC
}

这是监听 ws 获取最新 5 levels 的 orderbook 的 channel.

wsPartialDepthHandler 在库中是定义的一个虚方法, 需要在外部实现, 之后可以将价格写入数据库, 或者主动触发一些事情.

errHandler 在出错的时候处理错误, 记录日志的方法.

doneC 和 stopC 是底层定义好的两个 channel, 当需要退出监听时向 stopC 写一个数据, 当需要阻塞主进程, 进入监听死循环的时候从 doneC 读一个数据.

go func() {…} 是开启了一个协程, 阻塞 5 秒之后向 stopC 写一个数据, 进程即退出.

末尾从 doneC 读一个数据, 由于此通道永远不会有数据写入, 所以主进程到这里阻塞住.

JSON 格式化

引入头文件 import "encoding/json"

1
2
3
4
5
6
7
8
// JSON 对象 => 字符串
bytes []byte, _ := json.Marshal(JSON)

// 字符串 => JSON 对象
var JSON 类型
if err := json.Unmarshal([]byte(str), &JSON); err != nil {
panic(err)
}

参考文档: https://gobyexample.com/json

我们将获取到的买卖价格数据, 组成数组

1
2
3
askbid := []string{event.Bids[0].Price, event.Asks[0].Price}
askbidBytes, \_ := json.Marshal(askbid)
askbidStr := string(askbidBytes)

将数据写入 Redis 数据库

我们将获取到的盘口价格数据, 存储到 zset 中进行缓存.

数据结构为 zset, score: timestamp 时间戳, member: [ask, bid]

1
err = client.ZAdd("z_askbid_"+event.Symbol, &redis.Z{Score: float64(time.Now().Unix()), Member: askbidStr}).Err()

获取最新价格 zrange z_askbid_BTCUSDT -1 -1 WITHSCORES

关于代码换行

在有些语言里面, 通过换行可以让代码更易懂.

但是上面写入 redis 数据库的部分, 有没有太长了一些, 可以按如下的方法将其拆分成多行

1
2
3
4
5
6
err = client.ZAdd(
"z_askbid_"+event.Symbol,
&redis.Z{
Score: float64(time.Now().Unix()),
Member: askbidStr,
}).Err()

但是注意一点是 golang 是无 ; 结尾的语言, 不能在有完整语义的地方进行换行, 例如下面的做法就是错误的

1
2
3
4
5
6
7
8
err = client
.ZAdd(
"z_askbid_"+event.Symbol,
&redis.Z{
Score: float64(time.Now().Unix()),
Member: askbidStr,
})
.Err()

因为编译器会认为是这样的

1
2
3
4
5
6
7
8
err = client;
.ZAdd(
"z_askbid_"+event.Symbol,
&redis.Z{
Score: float64(time.Now().Unix()),
Member: askbidStr,
});
.Err();
Donate - Support to make this site better.
捐助 - 支持我让我做得更好.