概述
- 在即时通讯(IM)系统开发中,好友列表和群组管理是两个核心功能,它们为用户提供了便捷的交流平台
- 使用Go语言(通常简称为Go)来构建这些功能,可以充分利用其高并发、简洁易读以及强大的标准库支持等优势
- 本文将概述如何使用Go语言设计和实现一个IM系统中的好友列表显示和群组管理功能
基于MVC的目录设计
im-project
├── go.mod
├── main.go 主程序
├── model 模型层
│ ├── community.go
│ └── contact.go
├── views 模板层
│ └── chat
│ ├── concat.html
│ └── login.html
├── ctrl 控制器层
│ └── contact.go
├── service 服务包
│ └── contact.go
├── utils 工具包
│ └── parse.go
主程序
在 main.go 核心代码
package main
import (
"net/http"
"im-project/ctrl"
)
func main() {
// 其他略 ...
http.HandleFunc("/contact/addfriend", ctrl.Addfriend)
http.HandleFunc("/contact/loadfriend", ctrl.LoadFriend)
http.HandleFunc("/contact/createcommunity", ctrl.CreateCommunity)
http.HandleFunc("/contact/joincommunity", ctrl.JoinCommunity)
http.HandleFunc("/contact/loadcommunity", ctrl.LoadCommunity)
// 其他略 ...
}
- 这里可见,有添加好友,加载好友列表,加入群聊,加载群聊
- /contact/addfriend 参数userid,dstid 这里假设自动添加好友, 简化了加好友的流程
- 比如用户10000添加好友10086, 就会往contact表中添加俩条记录
- 一条ownerid =10000, dstobj=10086
- 一条ownerid =10086, dstobj= 10000
- /contact/loadfriend 显示全部好友, 参数userid
- /contact/createcommunity 建群, 头像pic, 名称name, 备注memo, 创建者userid
- /contact/loadcommunity 显示全部群 参数userid
- /contact/joincommunity 加群, 参数userid,dstid
模型层
在 model/contact.go 中, 这里是联系人(好友或群)
package model
import "time"
//好友和群都存在这个表里面, 可根据具体业务做拆分
type Contact struct {
Id int64 `xorm:"pk autoincr bigint(20)" form:"id" json:"id"`
Ownerid int64 `xorm:"bigint(20)" form:"ownerid" json:"ownerid"` // 记录是谁的
Dstobj int64 `xorm:"bigint(20)" form:"dstobj" json:"dstobj"` // 对端信息
Cate int `xorm:"int(11)" form:"cate" json:"cate"` // 类型: 用户 | 群
Memo string `xorm:"varchar(120)" form:"memo" json:"memo"` // 备注
Createat time.Time `xorm:"datetime" form:"createat" json:"createat"` // 创建时间
}
const (
CONCAT_CATE_USER = 0x01
CONCAT_CATE_COMUNITY = 0x02
)
在 model/community.go 中, 这里单指群模型
package model
import "time"
type Community struct {
Id int64 `xorm:"pk autoincr bigint(20)" form:"id" json:"id"`
Name string `xorm:"varchar(30)" form:"name" json:"name"` // 名称
Ownerid int64 `xorm:"bigint(20)" form:"ownerid" json:"ownerid"` // 群主ID
Icon string `xorm:"varchar(250)" form:"icon" json:"icon"` // 群 logo
Cate int `xorm:"int(11)" form:"cate" json:"cate"` // 类型
Memo string `xorm:"varchar(120)" form:"memo" json:"memo"` // 描述
Createat time.Time `xorm:"datetime" form:"createat" json:"createat"` // 创建时间
}
const (
COMMUNITY_CATE_COM = 0x01
)
服务包
service/contact.go
package service
import (
"time"
"im-project/model"
"errors"
)
type ContactService struct {}
//自动添加好友
func (service *ContactService) AddFriend(
userid,//用户id 10086,
dstid int64 ) error {
//如果加自己
if userid==dstid {
return errors.New("不能添加自己为好友啊")
}
//判断是否已经加了好友
tmp := model.Contact{}
//查询是否已经是好友
// 条件的链式操作
DbEngin.Where("ownerid = ?",userid).
And("dstid = ?",dstid).
And("cate = ?",model.CONCAT_CATE_USER).
Get(&tmp)
//获得1条记录
//count()
//如果存在记录说明已经是好友了不加
if tmp.Id>0{
return errors.New("该用户已经被添加过啦")
}
//事务,
session := DbEngin.NewSession();
session.Begin()
//插自己的
_,e2 := session.InsertOne(model.Contact{
Ownerid:userid,
Dstobj:dstid,
Cate:model.CONCAT_CATE_USER,
Createat:time.Now(),
})
//插对方的
_,e3 := session.InsertOne(model.Contact{
Ownerid:dstid,
Dstobj:userid,
Cate:model.CONCAT_CATE_USER,
Createat:time.Now(),
})
//没有错误
if e2==nil && e3==nil{
//提交
session.Commit()
return nil
}else{
//回滚
session.Rollback()
if e2!=nil{
return e2
}else{
return e3
}
}
}
func (service *ContactService) SearchComunity(userId int64) ([]model.Community){
conconts := make([]model.Contact,0)
comIds :=make([]int64,0)
DbEngin.Where("ownerid = ? and cate = ?",userId,model.CONCAT_CATE_COMUNITY).Find(&conconts)
for _,v := range conconts{
comIds = append(comIds,v.Dstobj);
}
coms := make([]model.Community,0)
if len(comIds)== 0{
return coms
}
DbEngin.In("id",comIds).Find(&coms)
return coms
}
//加群
func (service *ContactService) JoinCommunity(userId,comId int64) error{
cot := model.Contact{
Ownerid:userId,
Dstobj:comId,
Cate:model.CONCAT_CATE_COMUNITY,
}
DbEngin.Get(&cot)
if(cot.Id==0){
cot.Createat = time.Now()
_,err := DbEngin.InsertOne(cot)
return err
}else{
return nil
}
}
//建群
func (service *ContactService) CreateCommunity(comm model.Community) (ret model.Community,err error){
if len(comm.Name)==0{
err = errors.New("缺少群名称")
return ret,err
}
if comm.Ownerid==0{
err = errors.New("请先登录")
return ret,err
}
com := model.Community{
Ownerid:comm.Ownerid,
}
num,err := DbEngin.Count(&com)
if(num>5){
err = errors.New("一个用户最多只能创见5个群")
return com,err
}else{
comm.Createat=time.Now()
session := DbEngin.NewSession()
session.Begin()
_,err = session.InsertOne(&comm)
if err!=nil{
session.Rollback();
return com,err
}
_,err =session.InsertOne(
model.Contact{
Ownerid:comm.Ownerid,
Dstobj:comm.Id,
Cate:model.CONCAT_CATE_COMUNITY,
Createat:time.Now(),
})
if err!=nil{
session.Rollback();
}else{
session.Commit()
}
return com,err
}
}
//查找好友
func (service *ContactService) SearchFriend(userId int64) ([]model.User){
conconts := make([]model.Contact,0)
objIds :=make([]int64,0)
DbEngin.Where("ownerid = ? and cate = ?",userId,model.CONCAT_CATE_USER).Find(&conconts)
for _,v := range conconts{
objIds = append(objIds,v.Dstobj);
}
coms := make([]model.User,0)
if len(objIds)== 0{
return coms
}
DbEngin.In("id",objIds).Find(&coms)
return coms
}
控制器
ctrl/contact.go
package ctrl
import (
"net/http"
"im-project/util"
"im-project/service"
"im-project/args"
)
var contactService service.ContactService
func Addfriend(w http.ResponseWriter, req *http.Request) {
//定义一个参数结构体
/*
request.ParseForm()
mobile := request.PostForm.Get("mobile")
passwd := request.PostForm.Get("passwd")
*/
var arg args.ContactArg
util.Bind(req,&arg)
// 调用service
err := contactService.AddFriend(arg.Userid,arg.Dstid)
if err!=nil {
util.RespFail(w,err.Error())
} else {
util.RespOk(w,nil,"好友添加成功")
}
}
func LoadFriend(w http.ResponseWriter, req *http.Request){
var arg args.ContactArg
//如果这个用的上,那么可以直接
util.Bind(req,&arg)
users := contactService.SearchFriend(arg.Userid)
util.RespOkList(w,users,len(users))
}
func LoadCommunity(w http.ResponseWriter, req *http.Request){
var arg args.ContactArg
//如果这个用的上,那么可以直接
util.Bind(req,&arg)
comunitys := contactService.SearchComunity(arg.Userid)
util.RespOkList(w,comunitys,len(comunitys))
}
func JoinCommunity(w http.ResponseWriter, req *http.Request){
var arg args.ContactArg
//如果这个用的上,那么可以直接
util.Bind(req,&arg)
err := contactService.JoinCommunity(arg.Userid,arg.Dstid);
if err!=nil{
util.RespFail(w,err.Error())
}else {
util.RespOk(w,nil,"")
}
}
模板层
这里, 不再赘述UI层的相关编码