本人是搞移动客户端开发的,业余时间接触到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简易聊天系统后台源码分享的更多相关文章

  1. [干货]Chloe官网及基于NFine的后台源码毫无保留开放

    扯淡 经过不少日夜的赶工,Chloe 的官网于上周正式上线.上篇博客中LZ说过要将官网以及后台源码都会开放出来,为了尽快兑现我说过的话,趁周末,我稍微整理了一下项目的源码,就今儿毫无保留的开放给大家, ...

  2. NFine的后台源码

    Chloe官网及基于NFine的后台源码毫无保留开放   扯淡 经过不少日夜的赶工,Chloe 的官网于上周正式上线.上篇博客中LZ说过要将官网以及后台源码都会开放出来,为了尽快兑现我说过的话,趁周末 ...

  3. 3D语音天气球(源码分享)——创建可旋转的3D球

    开篇废话: 在9月份时参加了一个网站的比赛,比赛的题目是需要使用第三方平台提供的服务做出创意的作品. 于是我选择使用语音服务,天气服务,Unity3D,Android来制作一个3D语音天气预报,我给它 ...

  4. 火热的线上APP的源码分享,开箱即用

    这篇文章是写给iOS的程序员或产品经理的,同样,对于入门学习iOS开发的人,也是一个很好的实战演练,因为这里分享的是一个已经上架的.拿了源码就能正常运行起来的项目. 在介绍这个项目的源码分享之前,小编 ...

  5. Android精品源码分享第四波袭来,免费下载!

    今天又汇总了几个优质的源码分享出来给大家!希望可以帮到需要的朋友~1.Android实现-带动画的饼图控件 分享的是Android技术相关的源码内容,希望对大家的Android学习有帮助.带动画的饼图 ...

  6. [DeviceOne开发]-土地销售项目源码分享

    一.简介 这个是一个真实项目开源,虽然不是很花哨,但是中规中矩,小细节处理的也很好,非常值得参考和借鉴.里面的数据都缓存到本地,可以离线运行,但是调整一下代码,马上就可以和服务端完全对接.后续会有详细 ...

  7. WP8.1&Win10幸运大转盘源码分享

    先AD一下我的群:Win10开发者群:53078485 最近在写一个APP,其中需要一个转盘动画的源码,找了很多但是都没有找到,无奈只好自己来写,写完效果自己还是比较满意的,分享出来,有需要的童鞋可以 ...

  8. 3D语音天气球(源码分享)——完结篇

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 开篇废话: 由于这篇文章是本系列最后一篇,有必要进行简单的回顾和思路整理. 这个程序是由两 ...

  9. 3D语音天气球(源码分享)——在Unity中使用Android语音服务

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 开篇废话: 这个项目准备分四部分介绍: 一:创建可旋转的"3D球":3 ...

随机推荐

  1. BZOJ1393 [Ceoi2008]knights

    题意...上ceoi官网看吧... 首先打一下sg函数发现必胜态和必败态的分布位置是有规律的 于是我们只要知道最长步数的必胜态和最长步数的必败态哪个更长就可以了 然后再打一下步数的表...发现必败态的 ...

  2. JAVA EE企业级开发四步走完全攻略 [转]

    http://bbs.51cto.com/thread-550558-1.html 本文是J2EE企业级开发四步走完全攻略索引,因内容比较广泛,涉及整个JAVA EE开发相关知识,这是一个长期的计划, ...

  3. mysql在一台服务器搭建主从1

    1. 登录mysq的方法:  mysql-S /tmp/mysql.sock 登录3306  mysql -S /tmp/mysql_slave.sock 登录3307 mysql -h 127.0. ...

  4. 如何在 Linux 中整理磁盘碎片

    有一个神话是 linux 的磁盘从来不需要整理碎片.在大多数情况下这是真的,大多数因为是使用的是优秀的日志文件系统(ext3.4等等)来处理文件系统.然而,在一些特殊情况下,碎片仍旧会产生.如果正巧发 ...

  5. 哈希(Hask)

     编辑 Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射 ...

  6. NOIP 2000解题报告

    题目简单,思路很快就有,关键是代码实现能力,大概3个多小时完成.第一题:题目大意:将一个10进制数N转换成-B进制数 (负进制转换):B<=20, N(-32768<=N<=3276 ...

  7. android自定义控件实例(Linearlayout组合TextView和ImageView)

    2013-12-18 11:25:22 转载自: http://www.open-open.com/lib/view/open1328836804515.html 很多时候android常用的控件不能 ...

  8. 'NSInteger' (aka 'long') to 'int32

    怎么去掉Xcode工程中的某种类型的警告 Implicit conversion loses integer precision: 'NSInteger' (aka 'long') to 'int32 ...

  9. 标准库源码--wsgi服务器

    功能模块化带来可自由组装的便利: 使用python的mixin特性装配 class ThreadHTTPServer(ThreadingMixin, HTTPServer): pass 上面表示1个请 ...

  10. C语言中输入输出函数

    1.1.1 格式化输入输出函数Turbo C2.0 标准库提供了两个控制台格式化输入. 输出函数printf() 和scanf(), 这两个函数可以在标准输入输出设备上以各种不同的格式读写数据.pri ...