推荐理由

Golang官方标准库实现的websocket在功能上有些欠缺,本次介绍的gorilla/websocket库,是Gorilla出品的速度快、质量高,并且被广泛使用的websocket库,很好的弥补了标准库功能上的欠缺。另外Gorilla Web toolkit包含多个实用的HTTP应用相关的工具库,感兴趣可以到官网主页https://www.gorillatoolkit.org自取。

功能介绍

gorilla/websocket库是 RFC 6455 定义的websocket协议的一种实现,在数据收发方面,提供Data Messages、Control Messages两类message粒度的读写API;性能方面,提供Buffers和Compression的相关配置选项;安全方面,可通过CheckOrigin来控制是否支持跨域。

gorilla/websocket库和官方实现的对比

摘自 gorilla GitHub 主页

github.com/gorillagolang.org/x/netRFC 6455 FeaturesPasses Autobahn Test SuiteYesNoReceive fragmented messageYesNo, see note 1Send close messageYesNoSend pings and receive pongsYesNoGet the type of a received data messageYesYes, see note 2Other FeaturesCompression ExtensionsExperimentalNoRead message using io.ReaderYesNo, see note 3Write message using io.WriteCloserYesNo, see note 3

Notes:

Large messages are fragmented in Chrome's new WebSocket implementation.

The application can get the type of a received data message by implementing a Codec marshalfunction.

The go.net io.Reader and io.Writer operate across WebSocket frame boundaries. Read returns when the input buffer is full or a frame boundary is encountered. Each call to Write sends a single frame message. The Gorilla io.Reader and io.WriteCloser operate on a single WebSocket message.

使用指南

安装 go get github.com/gorilla/websocket 基础示例

下面以一个简单的echo来说明gorilla/websocket库基本使用。

client代码:

package main import (  "flag"  "log"  "net/url"  "os"  "os/signal"  "time"  "github.com/gorilla/websocket" ) var addr = flag.String("addr", "localhost:8080", "http service address") func main() {  flag.Parse()  log.SetFlags(0)     // 用来接收命令行的终止信号  interrupt := make(chan os.Signal, 1)  signal.Notify(interrupt, os.Interrupt)     // 和服务端建立连接  u := url.URL{Scheme: "ws", Host: *addr, Path: "/echo"}  log.Printf("connecting to %s", u.String())  c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)  if err != nil {   log.Fatal("dial:", err)  }  defer c.Close()  done := make(chan struct{})  go func() {   defer close(done)   for {             // 从接收服务端message    _, message, err := c.ReadMessage()    if err != nil {     log.Println("read:", err)     return    }    log.Printf("recv: %s", message)   }  }()  ticker := time.NewTicker(time.Second)  defer ticker.Stop()  for {   select {   case