如果只是想了解chat的实现方式,在gorilla和revel框架里面都有完整的chat实例可以提供参考。本篇讲解的是,如何基于martini实现websocket的聊天。

配置步骤:

1 已经安装了go命令,配置了GOPATH

2 安装gorilla/websocket

go get github.com/gorilla/websocket

3 安装martini

go get github.com/go-martini/martini

项目文件列表

$GOPATH/demo/home.html
$GOPATH/demo/martini_ws.go

home.html 代码

<!DOCTYPE html>
<html lang="en">
<head>
<title>Chat Example</title>
<script type="text/javascript">
window.onload = function () {
var conn;
var msg = document.getElementById("msg");
var log = document.getElementById("log"); function appendLog(item) {
var doScroll = log.scrollTop === log.scrollHeight - log.clientHeight;
log.appendChild(item);
if (doScroll) {
log.scrollTop = log.scrollHeight - log.clientHeight;
}
} document.getElementById("form").onsubmit = function () {
if (!conn) {
return false;
}
if (!msg.value) {
return false;
}
conn.send(msg.value);
msg.value = "";
return false;
}; if (window["WebSocket"]) {
conn = new WebSocket("ws://{{$}}/ws");
conn.onclose = function (evt) {
var item = document.createElement("div");
item.innerHTML = "<b>Connection closed.</b>";
appendLog(item);
};
conn.onmessage = function (evt) {
var messages = evt.data.split('\n');
for (var i = ; i < messages.length; i++) {
var item = document.createElement("div");
item.innerText = messages[i];
appendLog(item);
}
};
} else {
var item = document.createElement("div");
item.innerHTML = "<b>Your browser does not support WebSockets.</b>";
appendLog(item);
}
};
</script>
<style type="text/css">
html {
overflow: hidden;
} body {
overflow: hidden;
padding: ;
margin: ;
width: %;
height: %;
background: gray;
} #log {
background: white;
margin: ;
padding: .5em .5em .5em .5em;
position: absolute;
top: .5em;
left: .5em;
right: .5em;
bottom: 3em;
overflow: auto;
} #form {
padding: .5em .5em;
margin: ;
position: absolute;
bottom: 1em;
left: 0px;
width: %;
overflow: hidden;
} </style>
</head>
<body>
<div id="log"></div>
<form id="form">
<input type="submit" value="Send" />
<input type="text" id="msg" size=""/>
</form>
</body>
</html>

martini_ws.go代码

package main

import (
"fmt"
"github.com/go-martini/martini"
"github.com/gorilla/websocket"
"log"
"net/http"
"text/template"
) const (
readBufferSize =
writeBufferSize =
) type Client struct {
conn *websocket.Conn
messages chan []byte
} var clients map[*Client]bool // 存储所有的链接
var broadcast chan []byte // 广播聊天的chan
var addClients chan *Client // 新链接进来的chan func (c *Client) readPump() {
for {
_, message, err := c.conn.ReadMessage()
if err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
log.Printf("error: %v", err)
}
break
}
fmt.Printf("receive message is :%s\n", message)
broadcast <- message
}
} func (c *Client) writePump() {
for {
select {
case message := <-c.messages:
fmt.Printf("send message is :%s\n", message)
c.conn.WriteMessage(, message)
}
}
} func manager() { clients = make(map[*Client]bool)
broadcast = make(chan []byte, )
addClients = make(chan *Client) for {
select {
case message := <-broadcast:
for client := range clients {
select {
case client.messages <- message:
default:
close(client.messages)
delete(clients, client)
}
}
case itemClient := <-addClients:
clients[itemClient] = true
}
}
} func main() { var homeTemplate = template.Must(template.ParseFiles("home.html")) m := martini.Classic() m.Get("/", func(res http.ResponseWriter, req *http.Request) { res.Header().Set("Content-Type", "text/html; charset=utf-8")
homeTemplate.Execute(res, req.Host)
}) m.Get("/ws", func(res http.ResponseWriter, req *http.Request) { // res and req are injected by Martini
conn, err := websocket.Upgrade(res, req, nil, readBufferSize, writeBufferSize)
if err != nil {
log.Println(err)
return
}
client := &Client{conn: conn, messages: make(chan []byte, )}
addClients <- client
go client.writePump()
client.readPump()
}) go manager() m.RunOnAddr(":3010")
//m.Run() }

按照上面的步骤建好文件,就可以运行了。m.RunOnAddr 可以改成你需要的端口

执行命令:

go run martini_ws.go

在浏览器输入 http://localhost:3010 就能访问你本机的聊天服务了

参考地址

https://github.com/patcito/martini-gorilla-websocket-chat-example

  

go语言从零学起(四) -- 基于martini和gorilla实现的websocket聊天实例的更多相关文章

  1. go语言从零学起(三) -- chat实现的思考

    要通过go实现一个应用场景: 1 建立一个websocket服务 2 维护在线用户的链接 3 推送消息和接受用户的操作 列出需求,很显然的想到了chat模型.于是研究了revel框架提供的sample ...

  2. go语言从零学起(一) -- 文档教程篇

    先记录一下自己学go语言的出发点 作为一个phper,精通一门底层语言一直是努力的目标. 相对于c,c++,go语言不需要过多的关注指针,内存释放,一两行代码就能跑起一个server服务,简直不要太简 ...

  3. go语言从零学起(二)--list循环删除元素(转载)

    本篇系转载 在使用go的container/list的package时,你可能会无意间踩一个小坑,那就是list的循环删除元素. list删除元素,直观写下来的代码如下: package main i ...

  4. 从零学脚手架(四)---babel

    如果此篇对您有所帮助,在此求一个star.项目地址: OrcasTeam/my-cli 接下来介绍一个打包编译过程中一个极为重要的工具--babel. ES6的枷锁 细心的朋友可以知道,在之前打包编译 ...

  5. 带你从零学ReactNative开发跨平台App开发(四)

    ReactNative跨平台开发系列教程: 带你从零学ReactNative开发跨平台App开发(一) 带你从零学ReactNative开发跨平台App开发(二) 带你从零学ReactNative开发 ...

  6. 带你从零学ReactNative开发跨平台App开发-[react native 仿boss直聘](十三)

    ReactNative跨平台开发系列教程: 带你从零学ReactNative开发跨平台App开发(一) 带你从零学ReactNative开发跨平台App开发(二) 带你从零学ReactNative开发 ...

  7. 带你从零学ReactNative开发跨平台App开发[expo 打包发布](八)

    ReactNative跨平台开发系列教程: 带你从零学ReactNative开发跨平台App开发(一) 带你从零学ReactNative开发跨平台App开发(二) 带你从零学ReactNative开发 ...

  8. 从头开始学JavaScript (四)——操作符

    原文:从头开始学JavaScript (四)--操作符 一.一元操作符 1.自增自减操作符:分为前置型和后置型: 前置型:++a;--a; 后置型:a++;a--; 例: <script typ ...

  9. C语言老司机学Python (五)

    今天看的是标准库概览. 操作系统接口: 用os模块实现. 针对文件和目录管理,还有个shutil模块可以用. 例句: import os os.getcwd() # 返回当前的工作目录 os.chdi ...

随机推荐

  1. 表格属性和BFC(block framing content)

    th和tr都是表示列但是 th有一个居中加粗的效果. 表单是由 : 1表单域:<form name=" " method="get/post"  acti ...

  2. Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 5. 参数

    上一个教程中,咪博士带大家学习了函数的使用.例如,line_without_moving 函数,可以让海龟先画出一条线段,然后再回来起点. def line_without_moving(): tur ...

  3. C# 之抽象类和抽象方法

    概述:abstract 关键字  抽象类不能被实例化,抽象方法不能有方法体,抽象类中的所有抽象方法必须在子类中重写(override ),一个抽象类可以同时包含抽象方法和非抽象方法. abstract ...

  4. Bootstrap面板

    前面的话 面板(Panels)是Bootstrap框架新增的一个组件,某些时候可能需要将某些 DOM 内容放到一个盒子里.对于这种情况,可以使用面板组件.本文将详细介绍Bootstrap面板 基础面板 ...

  5. Docker容器从一知半解到入门

    Docker是一个开源的.跨平台的应用容器引擎,可以让技术开发认用打包他们的应用以及一些依赖包到一个可移植的容器平台中,发布到任何流行的Linux操作系统上面,也可以在Windows和mac操作系统上 ...

  6. [代码]--python爬虫联系--爬取成语

    闲来无事,玩了个成语接龙,于是就想用python爬取下成语网站上的成语,直接上代码: #coding=utf-8 import requests from bs4 import BeautifulSo ...

  7. ceph 安装ceph问题汇总

    1.在不同节点安装ceph时,出现以下异常: 参考这里 ceph deploy RuntimeError: NoSectionError: No section: 'ceph' 解决方法: 在报错的机 ...

  8. Django-website 程序案例系列-18 多表跨表操作优化

    详解Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化 在数据库有外键的时候,使用 select_related() 和 pref ...

  9. Leetcode 50.Pow(x,n) By Python

    实现 pow(x, n) ,即计算 x 的 n 次幂函数. 示例 1: 输入: 2.00000, 10 输出: 1024.00000 示例 2: 输入: 2.10000, 3 输出: 9.26100 ...

  10. loj #117. 有源汇有上下界最小流

    题目链接 有源汇有上下界最小流,->上下界网络流 注意细节,边数组也要算上后加到SS,TT边. #include<cstdio> #include<algorithm> ...