go语言如何实现即时通讯聊天室
发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,本文小编为大家详细介绍"go语言如何实现即时通讯聊天室",内容详细,步骤清晰,细节处理妥当,希望这篇"go语言如何实现即时通讯聊天室"文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知
千家信息网最后更新 2026年10月31日go语言如何实现即时通讯聊天室
本文小编为大家详细介绍"go语言如何实现即时通讯聊天室",内容详细,步骤清晰,细节处理妥当,希望这篇"go语言如何实现即时通讯聊天室"文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。
实现的功能:公聊,私聊,修改用户名
只用到了四个类:
main.go:用来启动服务器
server.go:服务器相关代码
client.go:客户端相关代码,用户可以直接操作的可视化界面
user.go:用户类,用来封装用户的业务逻辑
架构图
完整代码
server.go
package mainimport ( "fmt" "io" "net" "sync" "time")type Server struct { Ip string Port int //在线用户列表 OnlineMap map[string]*User mapLock sync.RWMutex //消息广播的Channel Message chan string}func NewServer(ip string, port int) *Server { server := &Server{ Ip: ip, Port: port, OnlineMap: make(map[string]*User), Message: make(chan string), } return server}func (s *Server) Handler(conn net.Conn) { //业务逻辑 //fmt.Println("链接建立成功") user := NewUser(conn, s) user.Online() //监听用户是否活跃 isLive := make(chan bool) go func() { buf := make([]byte, 4096) for { n, error := conn.Read(buf) if n == 0 { user.Offline() return } if error != nil && error != io.EOF { fmt.Println("read error") } msg := string(buf[:n-1]) user.DoMessage(msg) //表示用户活跃 isLive <- true } }() for { select { case <-isLive: //当前用户活跃,不做任何时,激活select,重置定时器 case <-time.After(time.Second * 300): //超时,将user强制关闭 user.SendMsg("你被踢了") close(user.C) conn.Close() return } }}func (s *Server) ListenMessager() { for { msg := <-s.Message s.mapLock.Lock() for _, user := range s.OnlineMap { user.C <- msg } s.mapLock.Unlock() }}func (s *Server) BroadCast(user *User, msg string) { sendMsg := "[" + user.Addr + "]" + user.Name + ":" + msg s.Message <- sendMsg}func (s *Server) Start() { listener, error := net.Listen("tcp", fmt.Sprintf("%s:%d", s.Ip, s.Port)) if error != nil { fmt.Println("listener error...") return } defer listener.Close() go s.ListenMessager() for { conn, error := listener.Accept() if error != nil { fmt.Println("accept error...") continue } go s.Handler(conn) }}client.go
package mainimport ( "flag" "fmt" "io" "net" "os")type Client struct { ServerIp string ServerPort int Name string conn net.Conn flag int}func NewClient(serverIp string, serverPort int) *Client { client := &Client{ ServerIp: serverIp, ServerPort: serverPort, flag: 9999, } conn, error := net.Dial("tcp", fmt.Sprintf("%s:%d", serverIp, serverPort)) if error != nil { fmt.Println("net dial error...") return nil } client.conn = conn return client}func (c *Client) menu() bool { var flag int fmt.Println("1.公聊模式") fmt.Println("2.私聊模式") fmt.Println("3.修改用户名") fmt.Println("0.退出") fmt.Scanln(&flag) if flag >= 0 && flag <= 3 { c.flag = flag return true } else { fmt.Println(">>>>请输入合法数字<<<<") return false }}//修改用户名func (c *Client) UpdateName() bool { fmt.Println(">>>>请输入用户名") fmt.Scanln(&c.Name) sendMsg := "rename|" + c.Name + "\n" _, error := c.conn.Write([]byte(sendMsg)) if error != nil { fmt.Println("conn.write error...") return false } return true}//公聊func (c *Client) PublicChat() { var chatMsg string fmt.Println(">>>>请输入聊天内容,输入exit退出") fmt.Scanln(&chatMsg) for chatMsg != "exit" { if len(chatMsg) != 0 { msg := chatMsg + "\n" _, error := c.conn.Write([]byte(msg)) if error != nil { fmt.Println("conn.Write error....") break } } chatMsg = "" fmt.Println(">>>>请输入聊天内容,输入exit退出") fmt.Scanln(&chatMsg) }}//私聊func (c *Client) PrivateChat() { var remoteUser string var chatMsg string c.SelectUsers() fmt.Println(">>>>请输入聊天对象的用户名,输入exit退出") fmt.Scanln(&remoteUser) for remoteUser != "exit" { fmt.Println(">>>>请输入聊天内容,输入exit退出") fmt.Scanln(&chatMsg) for chatMsg != "exit" { if len(chatMsg) != 0 { msg := "to|" + remoteUser + "|" + chatMsg + "\n\n" _, error := c.conn.Write([]byte(msg)) if error != nil { fmt.Println("conn.Write error....") break } } chatMsg = "" fmt.Println(">>>>请输入聊天内容,输入exit退出") fmt.Scanln(&chatMsg) } c.SelectUsers() remoteUser = "" fmt.Println(">>>>请输入聊天对象的用户名,输入exit退出") fmt.Scanln(&remoteUser) }}//查询在线用户func (c *Client) SelectUsers() { sendMsg := "who\n" _, error := c.conn.Write([]byte(sendMsg)) if error != nil { fmt.Println("conn.Write error....") return }}//处理server返回的消息func (c *Client) DealResponse() { io.Copy(os.Stdout, c.conn)}func (c *Client) Run() { for c.flag != 0 { for c.menu() != true { } switch c.flag { case 1: //公聊 c.PublicChat() case 2: //私聊 c.PrivateChat() case 3: //修改用户名 c.UpdateName() } }}var serverIp stringvar serverPort intfunc init() { flag.StringVar(&serverIp, "ip", "127.0.0.1", "设置服务器IP地址(默认为127.0.0.1)") flag.IntVar(&serverPort, "port", 8888, "设置服务器端口(默认为8888)")}func main() { flag.Parse() client := NewClient(serverIp, serverPort) if client == nil { fmt.Println(">>>>链接服务器失败") return } go client.DealResponse() fmt.Println(">>>>链接服务器成功") client.Run()}user.go
package mainimport ( "net" "strings")type User struct { Name string Addr string C chan string conn net.Conn server *Server}func NewUser(conn net.Conn, server *Server) *User { userAddr := conn.RemoteAddr().String() user := &User{ Name: userAddr, Addr: userAddr, C: make(chan string), conn: conn, server: server, } go user.ListenMessage() return user}//用户上线func (u *User) Online() { u.server.mapLock.Lock() u.server.OnlineMap[u.Name] = u u.server.mapLock.Unlock() u.server.BroadCast(u, "上线")}//用户下线func (u *User) Offline() { u.server.mapLock.Lock() delete(u.server.OnlineMap, u.Name) u.server.mapLock.Unlock() u.server.BroadCast(u, "下线")}//给当前user的客户端发送消息func (u *User) SendMsg(msg string) { u.conn.Write([]byte(msg))}//处理消息func (u *User) DoMessage(msg string) { if msg == "who" { //查询当前在线用户 u.server.mapLock.Lock() for _, user := range u.server.OnlineMap { onlineMsg := "[" + user.Addr + "]" + user.Name + ":在线...\n" u.SendMsg(onlineMsg) } u.server.mapLock.Unlock() } else if len(msg) > 7 && msg[:7] == "rename|" { //修改用户名 rename|xxx newName := strings.Split(msg, "|")[1] //判断名字是否已经存在 _, ok := u.server.OnlineMap[newName] if ok { u.SendMsg("用户名已存在\n") } else { u.server.mapLock.Lock() delete(u.server.OnlineMap, u.Name) u.server.OnlineMap[newName] = u u.server.mapLock.Unlock() u.Name = newName u.SendMsg("用户名成功修改为:" + newName + "\n") } } else if len(msg) > 4 && msg[:3] == "to|" { //私聊 to|zhangsan|你好 //获取对方用户名 remoteName := strings.Split(msg, "|")[1] if remoteName == "" { u.SendMsg("用户名格式不对\n") return } //获取对方user remoteUser, ok := u.server.OnlineMap[remoteName] if !ok { u.SendMsg("用户不存在\n") return } //获取消息 msg := strings.Split(msg, "|")[2] if msg == "" { u.SendMsg("无消息内容,重新发送\n") } //发送消息 remoteUser.SendMsg(u.Name + "对您说:" + msg) } else { u.server.BroadCast(u, msg) }}func (u *User) ListenMessage() { for { msg := <-u.C u.conn.Write([]byte(msg + "\n")) }}main.go
package mainfunc main() { server := NewServer("127.0.0.1", 8888) server.Start()}读到这里,这篇"go语言如何实现即时通讯聊天室"文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注行业资讯频道。
用户
输入
用户名
内容
消息
服务器
服务
在线
聊天室
语言
通讯
成功
代码
文章
链接
处理
下线
业务
客户
客户端
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
互联网金融科技
科技创新与互联网经济
互联网最新的科技有限公司
合肥互联网科技公司
广州互联网络科技有限公司
腾讯科技 互联网女皇
团飞科技与伯堂互联网服务平台
中化能源互联网科技招聘
互联网科技创新服务
互联网科技公司实习生
广州市恰铎互联网科技有限公司
电子科技大学互联网创业大赛
科技类公司包括互联网吗
迪庆互联网科技招生
国大互联网教育科技有限公司薪资
南通创西澳互联网科技有限公司
易企秀互联网科技是做什么的
上海乐五互联网科技有限公司
科技信息时代互联网发展
绵阳真晨互联网科技有限公司
互联网科技公司起名
中资互联网科技
互联网公司 科技公司
北京互联网科技公司
互联网科技公司官网
字节跳动和互联网科技
长沙互联网科技
沐思想互联网科技有限公司
富国互联网金融科技混合基金
盐城市攀科互联网科技有限公司