如何编写第一个Golang Websocket客户端
#go #forexdata #websocket #realtimedata

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

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

许多GO和其他语言专家将不同意我的第二个声明。即使在提到的两个领域中Python很弱,我也喜欢它(我可能会再做一次)。

您将需要以前的编程经验,互联网连接和电子邮件地址来沿本教程工作。

让我们开始

获取WebSocket API密钥

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

Image description

设置环境

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

Image description

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

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

Image description

  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()

现在已经编写了管理连接的方法,它将从feed异步读取该过程,因为它是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

Image description

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

 // +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
    }
  }
}

另外,遍历我们的其他教程:
How To Write Your First Golang WebSocket Client

Your First Golang REST API Client

Your First PHP WebSocket Client

Python Development Kit for Forex and CFDs