聊天室代码练习


    package main

    import (
        "fmt"
        "io"
        "net"
        "os"
        "strings"
        "time"
    )

    type Clinet struct {
        Name string
        Addr string
        C    chan string
    }

    var onlineMap map[string]Clinet
    var message = make(chan string)

    func ErrFucn(s string, e error) {
        if e != nil {
            fmt.Println(s, e)
            os.Exit(1)
        }
    }

    func MakeMsg(clt Clinet, msg string) (buf string) {
        buf = fmt.Sprintf("[name:%s] => %s\n", clt.Name, msg)
        return
    }

    func Manger() {
        onlineMap = make(map[string]Clinet)
        for {
            msg := <-message
            for _, cln := range onlineMap {
                cln.C <- msg
            }
        }
    }

    func WriteToMsgClint(conn net.Conn, cln Clinet) {
        for msg := range cln.C {
            conn.Write([]byte(msg))
        }
    }

    func HandlerConnent(conn net.Conn) {
        defer conn.Close()
        netAddr := conn.RemoteAddr().String()
        isQuit := make(chan bool)
        hasDate := make(chan bool)

        // 全局广播
        clnt := Clinet{netAddr, netAddr, make(chan string)}
        onlineMap[clnt.Addr] = clnt
        go WriteToMsgClint(conn, clnt)
        message <- MakeMsg(clnt, "LOGIN")
        // 聊天室

        go func() {
            buf := make([]byte, 4096)
            for {
                n, err := conn.Read(buf)
                if n == 0 {
                    isQuit <- true
                    return
                }
                if err != nil && err != io.EOF {
                    fmt.Println("conn.Read err: ", err)
                    return
                }

                msg := string(buf[:n-1])
                if msg == "who" && len(msg) == 3 {
                    conn.Write([]byte("USER LIST:\n"))
                    for _, u := range onlineMap {
                        userInfo := fmt.Sprintf("[IP:%s] [NAME:%s]\n", u.Addr, u.Name)
                        conn.Write([]byte(userInfo))
                    }
                } else if len(msg) >= 8 && msg[:6] == "rename" {
                    newUser := strings.Split(msg, "|")[1]
                    clnt.Name = newUser
                    onlineMap[clnt.Addr] = clnt
                    conn.Write([]byte("用户更新成功!!!\n"))
                } else {
                    message <- MakeMsg(clnt, msg)
                }
                hasDate <- true
            }
        }()
        for {
            select {
            case <-isQuit:
                close(clnt.C)
                delete(onlineMap, clnt.Addr)
                message <- MakeMsg(clnt, "LOGOUT")
                return
            case <-hasDate:
                //
            case <-time.After(time.Second * 10):
                close(clnt.C)
                delete(onlineMap, clnt.Addr)
                message <- MakeMsg(clnt, "OVERTIME")
                return
            }
        }
    }

    func main() {
        listener, err := net.Listen("tcp", "127.0.0.1:8080")
        ErrFucn("net.Listen err", err)
        defer listener.Close()

        go Manger()
        for {
            conn, err := listener.Accept()
            ErrFucn("listener.Accept err:", err)
            go HandlerConnent(conn)
        }
    }

本文章使用limfx的vscode插件快速发布