在听取有关 Go(Golang)的讨论后,我决定探索它。我选择使用 Go 提取实时外汇数据,因为处理实时外汇数据是我的专业领域。
这是我的发现。

  • 设置可能是最简单的
  • 功能几乎没有问题。

许多 Go 和其他语言专家不同意我的第二个陈述。尽管 Python 在提到的两个方面较弱,但我喜欢它(我可能又做了一次)。

您将需要先前的编程经验、互联网连接和电子邮件地址,才能完成本教程。

让我们开始

获取 WebSocket API 密钥

在配置我们的 Go 环境之前,让我们从我们的登录网站接收我们的 FX WebSocket API 密钥。它是无偿的。登录您的帐户后创建您的 API 密钥并保留它。

 如何编写您的第一个 Golang WebSocket 客户端_Go

环境搭建

​首先从https://golang.org/doc/install​​下载并设置 Go 。

 如何编写您的第一个 Golang WebSocket 客户端_Go_02

我们需要采取以下三个简单的步骤:

  1. 安装 Golang 时。打开命令提示符并输入以下内容:
go version

 如何编写您的第一个 Golang WebSocket 客户端_Go_03

  1. 其次,您应该安装依赖项。
go get github.com/gorilla/websocket
  1. 是时候该写代码了!

让我们开始编码吧!我们将从开发基本框架开始。程序启动时会调用main()函数,同时导入必要的库。我们将在此示例中使用以下内容:

// +build ignore

package main

import (
"log"
"net/url"
"os"
"os/signal"
"time"
"github.com/gorilla/websocket"
)
func main() {
//Add progrma content here
}

将向其中添加几个变量,一个用于存储传入消息,另一个用于在程序结束时处理中断事件。类似于其他一些语言中的缓冲区,这些变量用作消息的管道。

Go 中的通道可以是单向的也可以是双向的。为了在程序结束后很好地整理,我们将向中断变量添加一个信号通知程序。

messageOut := make(chan string)
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)

我们现在将为 WebSocket 服务器连接生成 URL 并输出它,以便我们可以验证 URL。

u := url.URL{Scheme: "wss", Host: "marketdata.tradermade.com", Path: "/feedadv",}
log.Printf("connecting to %s", u.String())

下一步是开发代码以连接到服务器并处理各种与连接相关的结果。创建后,我们会扫描错误并在发现错误时通知用户。

本节的最后一行添加“defer c.Close()”,告诉程序在该方法完成时在此连接上调用 Close()。将初始延迟执行视为堆栈上的最终操作。

c, resp, err := websocket.DefaultDialer.Dial(u.String(), nil);

if err != nil {
log.Printf("handshake failed with status %d", resp.StatusCode)
log.Fatal("dial:", err)
}
//When the program closes close the connection
defer c.Close()

现在已经编写了管理连接的方法,它将异步地从提要中读取进程,因为它是一个 goroutine。它使用 C 在循环中读取消息。使用 ReadMessage(),返回通知或错误。

当收到消息时,首先进行检测,判断是否为连接消息;如果是,则返回包含用户密钥和必要符号的字符串。该代码输出错误消息并在收到错误时离开。

发送后,客户将回复一条定价消息。在此图中,我们将消息打印到屏幕上,但您可以根据需要在此处分析消息数据。

done := make(chan struct{})
go func() {
defer close(done)
for {
_, message, err := c.ReadMessage()
if err != nil {
log.Println("read:", err)
return
}
log.Printf("recv: %s", message)
if string(message) == "Connected"{
log.Printf("Send Sub Details: %s", message)
messageOut <- "{"userKey":"YOUR_API_KEY", "symbol":"EURUSD"}"
}
}
}()

该程序的最终组成部分看似复杂,但实际上很简单。由于 goroutine 是异步的,它不会锁定主线程。因此,如果没有这一部分,程序将返回,并且您的提要处理程序将停止。这个连续的循环是用来保持程序继续进行的。

ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case <-done:
return
case m := <-messageOut:
log.Printf("Send Message %s", m)
err := c.WriteMessage(websocket.TextMessage, []byte(m))
if err != nil {
log.Println("write:", err)
return
}

case t := <-ticker.C:
err := c.WriteMessage(websocket.TextMessage, []byte(t.String()))
if err != nil {
log.Println("write:", err)
return
}

case <-interrupt:
log.Println("interrupt")
// Cleanly close the connection by sending a close message and then
// waiting (with timeout) for the server to close the connection.
err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
if err != nil {
log.Println("write close:", err)
return
}

select {
case <-done:
case <-time.After(time.Second):
}

return
}
}

我们可以组合所有代码,指定你的 API _KEY,并将文件保存为 webSocketClient.go。
然后从终端使用以下命令启动您的代码:

go run websocketClient.go

 如何编写您的第一个 Golang WebSocket 客户端_数据_04

您可能会看到实时定价更新。您运行的第一个提取 FX 数据的 Websocket 客户端已成功完成。
下面是完整的应用程序代码:

// +build ignore
package main
import (
"log"
"net/url"
"os"
"os/signal"
"time"
"github.com/gorilla/websocket"
)

func main() {
//Create Message Out
messageOut := make(chan string)
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)
u := url.URL{Scheme: "wss", Host: "marketdata.tradermade.com", Path: "/feedadv",}
log.Printf("connecting to %s", u.String())
c, resp, err := websocket.DefaultDialer.Dial(u.String(), nil);
if err != nil {
log.Printf("handshake failed with status %d", resp.StatusCode)
log.Fatal("dial:", err)
}

//When the program closes close the connection
defer c.Close()
done := make(chan struct{})
go func() {
defer close(done)
for {
_, message, err := c.ReadMessage()
if err != nil {
log.Println("read:", err)
return
}
log.Printf("recv: %s", message)
if string(message) == "Connected"{
log.Printf("Send Sub Details: %s", message)
messageOut <- "{"userKey":"YOUR_API_KEY", "symbol":"EURUSD"}"
}
}

}()

ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case <-done:
return
case m := <-messageOut:
log.Printf("Send Message %s", m)
err := c.WriteMessage(websocket.TextMessage, []byte(m))
if err != nil {
log.Println("write:", err)
return
}
case t := <-ticker.C:
err := c.WriteMessage(websocket.TextMessage, []byte(t.String()))
if err != nil {
log.Println("write:", err)
return
}
case <-interrupt:
log.Println("interrupt")
// Cleanly close the connection by sending a close message and then
// waiting (with timeout) for the server to close the connection.
err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
if err != nil {
log.Println("write close:", err)
return
}
select {
case <-done:
case <-time.After(time.Second):
}
return
}
}
}