GO简易聊天系统后台源码分享
本人是搞移动客户端开发的,业余时间接触到golang这么个可爱的囊地鼠,于是就写了这么个测试项目:简易版的聊天系统,功能包括注册,登陆,群聊和单聊,无需使用mysql,数据都存在了文本里。本人纯粹兴趣,前后就几天搞出来的产物,想到哪里写到哪里,边查手册边写出来的,所以某些地方会有不合理的地方,但测试过没有bug,就当为新手同学们提供个参考吧,也给手贱点进来的老手们提供个笑料吧 >_<,最起码可以知道go里怎么做字符串拆分的,go方法返回多个参数是怎么写的,go里json数据时如何解析的,go是怎么接受客户端发来的http请求的,go是怎么获取本地时间的,go是如何读写本地文本的等等:
项目文件结构为:
src/GoStudy/main.go
src/GoStudy/user (此为文本,注册用户表)
src/GoStudy/chat (此为文本,群聊消息表)
src/GoStudy/singleChat (此为文本,单聊消息表)
src/login/login.go
src/register/register.go
src/chat/chat.go
src/constData/constData.go
src/tool/databaseTool.go
src/tool/jsonMaker.go
以下是代码:
main.go:
1 package main
2
3 import (
4 "fmt"
5 "log"
6 "net/http"
7
8 "constData"
9 "login"
10 "chat"
11 "register"
12 )
13
14 func main(){
15
16 openHttpListen()
17 }
18
19 func openHttpListen(){
20 http.HandleFunc("/",receiveClientRequest)
21 fmt.Println("go server start running...")
22
23 err := http.ListenAndServe(":9090",nil)
24 if err != nil {
25 log.Fatal("ListenAndServe: ",err)
26 }
27 }
28
29 func receiveClientRequest(w http.ResponseWriter,r *http.Request){
30
31 r.ParseForm()
32 fmt.Println("收到客户端请求: ",r.Form)
33 /*
34 fmt.Println("path",r.URL.Path)
35 fmt.Println("scheme",r.URL.Scheme)
36 fmt.Println(r.Form["url_long"])
37
38 for k,v := range r.Form {
39 fmt.Printf("----------\n")
40 fmt.Println("key:",k)
41 fmt.Println("value:",strings.Join(v,", "))
42 }
43 */
44 var tag string = r.FormValue("tag")
45 switch tag{
46 case constData.REQ_TAG_LOGIN:
47
48 login.ReceiveLogin(w ,r)
49
50 case constData.REQ_TAG_REGISTER:
51
52 register.ReceiveRegister(w,r)
53
54 case constData.REG_TAG_CHAT:
55
56 chat.ReceiveChat(w,r)
57
58 case constData.REQ_TAG_LASTEST_MESSAGE:
59
60 chat.ReceiveMsgReq(w,r)
61
62 default:
63 break
64 }
65
66 }
login.go:
package login import (
"fmt"
"net/http"
"strings"
"encoding/json"
"io"
"log" "tool"
"constData"
) var totalNickStr string func ReceiveLogin(w http.ResponseWriter,r *http.Request) { var nick string = r.FormValue("nick")
var password string = r.FormValue("password") var tempData string = ""
var userID string = checkUserDataExist(nick,password)
if userID != "" {
//登陆成功返回用户id,和当前数据库内所有用户信息 tempData = "{" +
tool.MakeJsonValue("code","success") + "," +
tool.MakeJsonValue("tag",constData.REQ_TAG_LOGIN) + "," +
tool.MakeJsonValue("result","1") + "," +
tool.MakeJsonValue("id",userID) + "," +
tool.MakeJsonValue1("userlist",totalNickStr) +
"}" } else {
//返回client登录失败,用户不存在 0
tempData = "{" +
tool.MakeJsonValue("code","success") + "," +
tool.MakeJsonValue("tag",constData.REQ_TAG_LOGIN) + "," +
tool.MakeJsonValue("result","0") + "," +
tool.MakeJsonValue("info","账号不存在,请重新输入或者注册一个新账号") +
"}"
}
fmt.Fprintf(w,tempData)
} func checkUserDataExist(nick string,password string) string { var currentLocalChat string = tool.ReadLocalFile(constData.DatabaseFile_User)
var currentLocalChatList []string = strings.Split(currentLocalChat,"\n")
var currentLocalChatLength int = len(currentLocalChatList) var count = 0;
totalNickStr = "["
for _,str := range currentLocalChatList { totalNickStr += str;
count++; if count < (currentLocalChatLength-1) {
totalNickStr += ",";
}
if count == currentLocalChatLength {
break
}
}
totalNickStr += "]" type Message struct {
ID, Nick, Password string
} var existUserID string = "";
dec := json.NewDecoder(strings.NewReader(currentLocalChat))
for {
var m Message
if err := dec.Decode(&m); err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
} var u string = m.Nick
var p string = m.Password
if u == nick && p == password {
existUserID = m.ID
}
} return existUserID
} func Substr(str string, start, length int) string {
rs := []rune(str)
rl := len(rs)
end := 0 if start < 0 {
start = rl - 1 + start
}
end = start + length if start > end {
start, end = end, start
} if start < 0 {
start = 0
}
if start > rl {
start = rl
}
if end < 0 {
end = 0
}
if end > rl {
end = rl
} return string(rs[start:end])
}
register.go:
package register import (
"net/http"
"fmt"
"strings"
"io"
"log"
"strconv" "tool"
"constData"
"encoding/json"
) var localUserData string func ReceiveRegister(w http.ResponseWriter,r *http.Request){ var nick string = r.FormValue("nick")
var password string = r.FormValue("password") var tempData string = ""
if checknickExist(nick) {
//注册失败
tempData = "{" +
tool.MakeJsonValue("code","success") + "," +
tool.MakeJsonValue("tag",constData.REQ_TAG_REGISTER) + "," +
tool.MakeJsonValue("result","0") + "," +
tool.MakeJsonValue("info","用户id:"+nick+"已被使用") +
"}" } else {
//注册成功 var tempList []string = strings.Split(localUserData,"\n")
var localUserCount int = len(tempList)
var currentUserID string
if localUserCount == 0 {
currentUserID = "10000"
}else {
currentUserID = strconv.Itoa(10000 + localUserCount - 1);
} tempData = "{" +
tool.MakeJsonValue("code","success") + "," +
tool.MakeJsonValue("tag",constData.REQ_TAG_REGISTER) + "," +
tool.MakeJsonValue("result","1") + "," +
tool.MakeJsonValue("id",currentUserID) +
"}" //把新账号入库 {"id:",10000"nick":"kate","password":"123abc"}
var newUserData string = "{" +
tool.MakeJsonValue("id",currentUserID) + "," +
tool.MakeJsonValue("nick",nick) + "," +
tool.MakeJsonValue("password",password) +
"}\n"
tool.WriteLocalFile(localUserData + newUserData,constData.DatabaseFile_User);
}
fmt.Fprintf(w,tempData) } func checknickExist(nick string) bool { localUserData = tool.ReadLocalFile(constData.DatabaseFile_User) type Message struct {
Nick, Password string
} dec := json.NewDecoder(strings.NewReader(localUserData))
for {
var m Message
if err := dec.Decode(&m); err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
} var u string = m.Nick
if u == nick {
return true
}
} return false
}
chat.go:
package chat
import (
"net/http"
"fmt"
"strings"
"time"
"strconv"
"encoding/json"
"tool"
"constData"
)
//收到客户度发送的一条聊天信息
func ReceiveChat(w http.ResponseWriter,r *http.Request){
//对方的userid
var chatToUserID string = r.FormValue("chatToUserID")
var userid string = r.FormValue("userid")
var nick string = r.FormValue("nick")
var content string = r.FormValue("content")
//读取本地时间
currentTime := time.Now()
var timeStr string = currentTime.Format(constData.DateFormat)
//获取当前本地聊天内容
if chatToUserID == "100" {
var currentLocalChat string = tool.ReadLocalFile(constData.DatabaseFile_Chat)
var currentLocalChatList []string = strings.Split(currentLocalChat,"\n")
var currentLocalChatLength int = len(currentLocalChatList)
//组合json形式字符串存入本地
var currentChatData string = "{" +
tool.MakeJsonValue("id",strconv.Itoa(currentLocalChatLength - 1)) + "," +
tool.MakeJsonValue("time",timeStr) + "," +
tool.MakeJsonValue("userid",userid) + "," +
tool.MakeJsonValue("nick",nick) + "," +
tool.MakeJsonValue("content",content) +
"}\n"
fmt.Println("新聊天数据:" + currentChatData)
var writeSuccess bool = tool.WriteLocalFile(currentChatData + currentLocalChat,constData.DatabaseFile_Chat);
var tempData string = ""
if writeSuccess {
tempData = "{" +
tool.MakeJsonValue("code","success") + "," +
tool.MakeJsonValue("tag",constData.DatabaseFile_Chat) + "," +
tool.MakeJsonValue("result","1") +
"}"
} else {
tempData = "{" +
tool.MakeJsonValue("code","success") + "," +
tool.MakeJsonValue("tag",constData.DatabaseFile_Chat) + "," +
tool.MakeJsonValue("result","0") + "," +
tool.MakeJsonValue("info","聊天信息入库出错") +
"}"
}
fmt.Fprintf(w, tempData)
} else {
var currentLocalChat string = tool.ReadLocalFile(constData.DatabaseFile_SINGLE_CHAT)
var currentLocalChatList []string = strings.Split(currentLocalChat,"\n")
var currentLocalChatLength int = len(currentLocalChatList)
//组合json形式字符串存入本地
var currentChatData string = "{" +
tool.MakeJsonValue("id",strconv.Itoa(currentLocalChatLength - 1)) + "," +
tool.MakeJsonValue("time",timeStr) + "," +
tool.MakeJsonValue("senderid",userid) + "," +
tool.MakeJsonValue("receiverid",chatToUserID) + "," +
tool.MakeJsonValue("content",content) +
"}\n"
fmt.Println("新聊天数据:" + currentChatData)
var writeSuccess bool = tool.WriteLocalFile(currentChatData + currentLocalChat,constData.DatabaseFile_SINGLE_CHAT);
var tempData string = ""
if writeSuccess {
tempData = "{" +
tool.MakeJsonValue("code","success") + "," +
tool.MakeJsonValue("tag",constData.DatabaseFile_Chat) + "," +
tool.MakeJsonValue("result","1") +
"}"
} else {
tempData = "{" +
tool.MakeJsonValue("code","success") + "," +
tool.MakeJsonValue("tag",constData.DatabaseFile_Chat) + "," +
tool.MakeJsonValue("result","0") + "," +
tool.MakeJsonValue("info","聊天信息入库出错") +
"}"
}
fmt.Fprintf(w, tempData)
}
}
//收到客户端发送的请求最新几条聊天内容协议
func ReceiveMsgReq(w http.ResponseWriter,r *http.Request){
maxCount,_ := strconv.Atoi(r.FormValue("count"))
var chatUserID string = r.FormValue("chatuserid")
var selfid string = r.FormValue("selfid")
if chatUserID == "100"{
//获取当前本地聊天内容
var currentLocalChat string = tool.ReadLocalFile(constData.DatabaseFile_Chat)
var tempData string
if currentLocalChat == "noExist" {
tempData = "{" +
tool.MakeJsonValue("code","success") + "," +
tool.MakeJsonValue("tag",constData.REQ_TAG_LASTEST_MESSAGE) + "," +
tool.MakeJsonValue("result","0") + "," +
tool.MakeJsonValue("chatuserid",chatUserID) + "," +
tool.MakeJsonValue("info","聊天信息不存在") +
"}"
} else {
var currentLocalChatList []string = strings.Split(currentLocalChat,"\n")
// var currentLocalChatLength int = len(currentLocalChatList)
var count = 0;
var tempStr = "["
for _,str := range currentLocalChatList {
// fmt.Println(index,str)
tempStr += str;
count++;
if count < (maxCount - 1) {
tempStr += ",";
}
if count == maxCount {
break
}
}
tempStr += "]"
tempData = "{" +
tool.MakeJsonValue("code","success") + "," +
tool.MakeJsonValue("tag",constData.REQ_TAG_LASTEST_MESSAGE) + "," +
tool.MakeJsonValue("result","1") + "," +
tool.MakeJsonValue("chatuserid",chatUserID) + "," +
tool.MakeJsonValue1("info",tempStr) +
"}"
}
fmt.Fprintf(w, tempData)
} else {
//获取当前本地聊天内容
var currentLocalChat string = tool.ReadLocalFile(constData.DatabaseFile_SINGLE_CHAT)
var tempData string
if currentLocalChat == "noExist" {
tempData = "{" +
tool.MakeJsonValue("code","success") + "," +
tool.MakeJsonValue("tag",constData.REQ_TAG_LASTEST_MESSAGE) + "," +
tool.MakeJsonValue("result","0") + "," +
tool.MakeJsonValue("chatuserid",chatUserID) + "," +
tool.MakeJsonValue("info","聊天信息不存在") +
"}"
} else {
var currentLocalChatList []string = strings.Split(currentLocalChat,"\n")
// var currentLocalChatLength int = len(currentLocalChatList)
var count = 0;
var tempStr = "["
for _,str := range currentLocalChatList {
// fmt.Println(index,str)
type Message struct {
ID, Time, Senderid,Receiverid,Content string
}
dec := json.NewDecoder(strings.NewReader(str))
var m Message
dec.Decode(&m)
var senderid string = m.Senderid
var receiverid string = m.Receiverid
if (senderid == selfid && receiverid == chatUserID) || (senderid == chatUserID && receiverid == selfid) {
tempStr += str;
count++;
if count < (maxCount - 1) {
tempStr += ",";
}
if count == maxCount {
break
}
} else {
continue
}
}
tempStr += "]"
tempData = "{" +
tool.MakeJsonValue("code","success") + "," +
tool.MakeJsonValue("tag",constData.REQ_TAG_LASTEST_MESSAGE) + "," +
tool.MakeJsonValue("result","1") + "," +
tool.MakeJsonValue("chatuserid",chatUserID) + "," +
tool.MakeJsonValue1("info",tempStr) +
"}"
}
fmt.Fprintf(w, tempData)
}
}
databaseTool.go:
package tool import (
"fmt"
"io/ioutil" ) func ReadLocalFile(filePath string) string { f,err := ioutil.ReadFile(filePath)
if err != nil{
fmt.Printf("读表错误: %s\n",err)
// panic(err)
return "notExist"
}
return string(f)
} func WriteLocalFile(val string,filePath string) bool { var content = []byte(val);
err := ioutil.WriteFile(filePath,content,0644)
if err != nil{
fmt.Printf("%s\n",err)
panic(err)
return false
} fmt.Println("==写文件成功: " + filePath + "==")
return true }
jsonMaker.go:
package tool
func MakeJsonValue(key string,val string) string {
var str string = "\"" + key + "\":" + "\"" + val + "\""
return str
}
//value不带双引号
func MakeJsonValue1(key string,val string) string {
var str string = "\"" + key + "\":" + "" + val + ""
return str
}
constData.go:
package constData const (
DateFormat string = "2006-01-02 15:04:02" //日期时间格式 DatabaseFile_Chat string = "chat"
DatabaseFile_User string = "user"
DatabaseFile_SINGLE_CHAT string = "singleChat" REQ_TAG_LOGIN string = "login"
REQ_TAG_REGISTER string = "register"
REG_TAG_CHAT string = "chat"
REQ_TAG_LASTEST_MESSAGE string = "lastestMsg"
)
三个文本内容格式:
user:
{"id":"10000","nick":"jd","password":"111111"}
{"id":"10001","nick":"zoe","password":"123456"}
{"id":"10002","nick":"frank","password":"qqqqqq"}
chat:
{"id":"3","time":"2015-01-22 15:14:22","userid":"10001","nick":"zoe","content":"就我两么"}
{"id":"2","time":"2015-01-22 15:11:22","userid":"10001","nick":"zoe","content":"我来了"}
{"id":"1","time":"2015-01-22 15:08:22","userid":"10000","nick":"jd","content":"我好无聊 谁和我聊聊天呀?"}
{"id":"0","time":"2015-01-22 15:06:22","userid":"10000","nick":"jd","content":"有人在么"}
singlechat:
{"id":"3","time":"2015-01-22 15:27:22","senderid":"10002","receiverid":"10000","content":"yes ,how do u know that?"}
{"id":"2","time":"2015-01-22 15:25:22","senderid":"10000","receiverid":"10002","content":"are you from usa?"}
{"id":"1","time":"2015-01-22 15:16:22","senderid":"10001","receiverid":"10000","content":"是的 怎么了"}
{"id":"0","time":"2015-01-22 15:15:22","senderid":"10000","receiverid":"10001","content":"你是女孩?"}
另外:
客户端代码就不放上来了,如果需有可以向我要,是unity3d的客户端,我邮箱:jia_ding@qq.com
GO简易聊天系统后台源码分享的更多相关文章
- [干货]Chloe官网及基于NFine的后台源码毫无保留开放
扯淡 经过不少日夜的赶工,Chloe 的官网于上周正式上线.上篇博客中LZ说过要将官网以及后台源码都会开放出来,为了尽快兑现我说过的话,趁周末,我稍微整理了一下项目的源码,就今儿毫无保留的开放给大家, ...
- NFine的后台源码
Chloe官网及基于NFine的后台源码毫无保留开放 扯淡 经过不少日夜的赶工,Chloe 的官网于上周正式上线.上篇博客中LZ说过要将官网以及后台源码都会开放出来,为了尽快兑现我说过的话,趁周末 ...
- 3D语音天气球(源码分享)——创建可旋转的3D球
开篇废话: 在9月份时参加了一个网站的比赛,比赛的题目是需要使用第三方平台提供的服务做出创意的作品. 于是我选择使用语音服务,天气服务,Unity3D,Android来制作一个3D语音天气预报,我给它 ...
- 火热的线上APP的源码分享,开箱即用
这篇文章是写给iOS的程序员或产品经理的,同样,对于入门学习iOS开发的人,也是一个很好的实战演练,因为这里分享的是一个已经上架的.拿了源码就能正常运行起来的项目. 在介绍这个项目的源码分享之前,小编 ...
- Android精品源码分享第四波袭来,免费下载!
今天又汇总了几个优质的源码分享出来给大家!希望可以帮到需要的朋友~1.Android实现-带动画的饼图控件 分享的是Android技术相关的源码内容,希望对大家的Android学习有帮助.带动画的饼图 ...
- [DeviceOne开发]-土地销售项目源码分享
一.简介 这个是一个真实项目开源,虽然不是很花哨,但是中规中矩,小细节处理的也很好,非常值得参考和借鉴.里面的数据都缓存到本地,可以离线运行,但是调整一下代码,马上就可以和服务端完全对接.后续会有详细 ...
- WP8.1&Win10幸运大转盘源码分享
先AD一下我的群:Win10开发者群:53078485 最近在写一个APP,其中需要一个转盘动画的源码,找了很多但是都没有找到,无奈只好自己来写,写完效果自己还是比较满意的,分享出来,有需要的童鞋可以 ...
- 3D语音天气球(源码分享)——完结篇
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 开篇废话: 由于这篇文章是本系列最后一篇,有必要进行简单的回顾和思路整理. 这个程序是由两 ...
- 3D语音天气球(源码分享)——在Unity中使用Android语音服务
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 开篇废话: 这个项目准备分四部分介绍: 一:创建可旋转的"3D球":3 ...
随机推荐
- [转]Web开发的发展史
之所以转这篇文章是因为它可以对web请求有大致的理解. 以下内容转自:http://www.open-open.com/news/view/19ed96a 英文原文: Full stack web d ...
- 如何在win7下配置IIS?
- 所思所想 关于asp.net界面业务分离
1.体会:使用ASP.NET控件来做前段是有很大的局限性的 2.使用拼接HTML的方式来写代码虽然不符合模式,但是有很大的灵活性 3.如果使用拼接字符串的方式来生成前台的代码,使用NV的话完全可以实现 ...
- 如何创建一个客户端回调:js获得服务端的内容?
答案:表面上看去就是前端的js调用服务的C#方法,本质就是ajax,通过XMLHttpRequest对象和服务端进行交互.回调:就说回过头来调用,按理说js是一种脚本语言,怎么能用来调用服务端的呢?就 ...
- linux 下crontabs使用
安装crontab:[root@CentOS ~]# yum install vixie-cron[root@CentOS ~]# yum install crontabs说明:vixie-cron软 ...
- HBase HMaster Architecture - HBase Master架构
HBase architecture follows the traditional master slave model where you have a master which takes de ...
- 常见JS(JavaScript)冲突解决方法
1.一般JS冲突解决办法 a.最容易出现的就是js的命名冲突 ①.变量名冲突 变量有全局变量和局部变量当全局变量变量和局部变量名称一致时,就会js冲突,由于变量传递数值或地址不同就会产生JavaScr ...
- 各种常用函数 (SQL)
数学函数 1.绝对值 S:select abs(-1) value O:select abs(-1) value from dual 2.取整(大) S:select ceiling(-1.001 ...
- 二模 (1) day1
第一题: 题目大意:给出N(N<=50)个小于1000的正整数Ai,和一个正整数max,和一个整数cur,从前往后依次对每个Ai,可以让cur+Ai 或者 cur-Ai,但是结果不能大于max, ...
- dos.orm学习地址
os.ORM(原Hxj.Data)于2009年发布.2015年正式开源,该组件已在数百个成熟项目中应用,是目前国内.Net用户量最多.最活跃.最完善的国产ORM.初期开发过程参考了NBear与MySo ...