最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Go語言實現(xiàn)簡單網(wǎng)絡聊天室(命令行模式)

 更新時間:2025年02月21日 10:19:27   作者:千年死緩  
這篇文章主要為大家詳細介紹了如何基于Go語言實現(xiàn)簡單網(wǎng)絡聊天室,文中的示例代碼簡潔易懂,有需要的小伙伴可以跟隨小編一起學習一下

實戰(zhàn)簡介

網(wǎng)絡聊天室(命令行模式)

要求:

  • 輸入網(wǎng)名,可以進入聊天室
  • 聊天內信息實時更新
  • 利用協(xié)程處理多任務并發(fā)

基于tcp協(xié)議實現(xiàn)功能

服務器端

接受用戶消息和循環(huán)轉發(fā)

對功能命令進行處理

  • ./cd1 或 ./menu 功能菜單
  • ./cd2 或 ./changeName 更改昵稱
  • ./cd3 或 ./online 在線用戶數(shù)量查詢
  • ./cd4 或 ./quit 退出聊天室

客戶端

接受服務器發(fā)送的信息并處理

接受用戶的輸入處理后發(fā)往服務器

結構和示例

用戶登錄示例

功能行命令測試

發(fā)送消息廣播測試

用戶退出示例

服務器端

基本流程

1. 初始化

init() 函數(shù)被調用,用于初始化全局變量:

  • 創(chuàng)建一個映射 onlineList 用來保存在線用戶的信息。
  • 創(chuàng)建一個帶緩沖的消息通道 message 用于廣播消息給所有在線用戶。

2. 主函數(shù) main()

  • 使用 net.Listen 監(jiān)聽 TCP 地址 "127.0.0.1:8080"。
  • 啟動 manger() 協(xié)程來監(jiān)聽消息通道 message,并將消息廣播給所有在線用戶。
  • 主循環(huán)中,使用 Accept 接受新的客戶端連接,并為每個客戶端啟動一個新的協(xié)程 handleConnection(conn)。

3. 處理客戶端連接 handleConnection(conn)

對于每個客戶端連接,首先增加在線用戶計數(shù) count。

調用 addUser(conn) 添加新用戶到在線用戶列表,并返回一個 client 結構體實例。

創(chuàng)建一個 quit 通道,用于在客戶端斷開連接時發(fā)送信號。

啟動兩個協(xié)程:

  • writeMsgToClient(conn, quit):從用戶的 userChannel 中讀取消息并發(fā)送給客戶端。
  • readClient(conn, quit):從客戶端讀取消息并處理。

監(jiān)聽 quit 通道以檢測客戶端是否斷開連接。

4. 添加新用戶 addUser(conn)

創(chuàng)建一個新的 client 實例,其中包含一個用于消息的通道 userChannel、客戶端連接 conn 和默認名稱(客戶端地址)。

將新用戶添加到 onlineList 映射中。

5. 管理消息廣播 manger()

從消息通道 message 中讀取消息,并將消息廣播給所有在線用戶。

6. 寫消息到客戶端 writeMsgToClient(conn, quit)

從客戶端的 userChannel 讀取消息,使用 module.Encode 對消息進行編碼,并通過客戶端連接 conn 發(fā)送給客戶端。

如果發(fā)生錯誤或客戶端斷開連接,關閉客戶端連接并發(fā)送信號到 quit 通道。

7. 讀取客戶端消息 readClient(conn, quit)

從客戶端讀取消息,根據(jù)消息的內容執(zhí)行不同的操作:

  • 如果消息是以 !@#$@!cd1changeName 開頭,則處理昵稱更改請求。
  • 如果消息是以 !@#$@!cd4exit 開頭,則處理客戶端退出請求。
  • 如果消息是以 !@#$@!menu 開頭,則向客戶端發(fā)送菜單命令。
  • 如果消息是以 !@#$@!cd3online 開頭,則向客戶端發(fā)送在線用戶數(shù)量。
  • 其他情況下,將消息廣播給所有在線用戶。

如果客戶端斷開連接,則發(fā)送信號到 quit 通道。

8. 處理客戶端退出

當 quit 通道接收到信號時,從在線用戶列表中刪除該客戶端,并減少在線用戶計數(shù)。

如果所有客戶端都已斷開連接,則輸出“等待用戶連接中…”。

代碼

package main

import (
	"bufio"         
	"chatRoom/chatRoom/module" // 消息的編碼和解碼模塊
	"fmt"          
	"io"             
	"log"            
	"net"            
	"strconv"        
	"strings"       
	"sync"           
	"time"          
)

// 定義客戶端結構體
type client struct {
	userChannel chan string // 用戶的消息通道
	conn        net.Conn    // 網(wǎng)絡連接
	name        string      // 用戶名
	addr        string      // 客戶端地址
}

// 定義在線用戶計數(shù)器
var count int

// 定義互斥鎖
var mu sync.Mutex

// 定義在線用戶列表
var onlineList map[string]*client

// 定義消息廣播通道
var message chan string

// 初始化函數(shù)
func init() {
	onlineList = make(map[string]*client) // 初始化在線用戶列表
	message = make(chan string, 1024)     // 初始化消息廣播通道
}

// 主函數(shù)
func main() {
	fmt.Println("端口監(jiān)聽中...")
	listener, err := net.Listen("tcp", "127.0.0.1:8080")
	if err != nil {
		log.Fatal(err) // 如果監(jiān)聽失敗,記錄錯誤并退出程序
	}
	defer listener.Close()
	time.Sleep(time.Second)
	fmt.Println("端口監(jiān)聽成功")

	// 啟動管理消息廣播的協(xié)程
	go manger()

	// 主循環(huán),接受客戶端連接
	for {
		conn, err := listener.Accept()
		if err != nil {
			continue
		}
		go handleConnection(conn)
	}
}

// 處理客戶端連接的函數(shù)
func handleConnection(conn net.Conn) {
	defer conn.Close()

	count++ // 增加在線用戶計數(shù)

	fmt.Println("有新用戶連接服務,當前連接數(shù):", count)

	// 添加新用戶
	addUser(conn)

	// 創(chuàng)建退出信號通道
	var quit = make(chan bool)

	// 啟動寫消息到客戶端的協(xié)程
	go writeMsgToClient(conn, quit)

	// 啟動讀取客戶端消息的協(xié)程
	go readClient(conn, quit)

	// 監(jiān)聽退出信號
	select {
	case <-quit:
		// 用戶下線處理
		connName := onlineList[conn.RemoteAddr().String()].name
		mu.Lock()
		close(onlineList[conn.RemoteAddr().String()].userChannel)
		mu.Unlock()
		mu.Lock()
		delete(onlineList, conn.RemoteAddr().String())
		mu.Unlock()
		count--
		message <- "< 系統(tǒng)消息 > [ " + connName + " ]" + "下線了 當前在線人數(shù) " + strconv.Itoa(len(onlineList)) + " 人"
		fmt.Println("有用戶下線了,當前連接數(shù):", count)
		if count == 0 {
			fmt.Println("等待用戶連接中...")
		}

		return
	}
}

// 修改用戶名的方法
func (c *client) changeName(newUserName string) bool {
	mu.Lock()
	defer mu.Unlock()
	// 更新用戶名
	c.name = newUserName
	return true
}

// 管理消息廣播的函數(shù)
func manger() {
	fmt.Println("開始監(jiān)聽 message通道")
	defer fmt.Println("結束監(jiān)聽 message通道")
	for msg := range message {
		mu.Lock()
		for _, v := range onlineList {
			v.userChannel <- msg
		}
		mu.Unlock()
	}
}

// 寫消息到客戶端的協(xié)程
func writeMsgToClient(conn net.Conn, quit chan bool) {
	fmt.Println(onlineList[conn.RemoteAddr().String()].name, "的信息通道監(jiān)聽成功")
	defer fmt.Println(onlineList[conn.RemoteAddr().String()].name, "的信息通道監(jiān)聽結束")
	for msg := range onlineList[conn.RemoteAddr().String()].userChannel {
		king, err := module.Encode(msg + "\n")
		if err != nil {
			fmt.Println("發(fā)送消息失敗")
			continue
		}
		_, err = conn.Write(king)
		if err != nil {
			fmt.Println("發(fā)送消息失敗")
			quit <- true
		}
	}
	fmt.Println("函數(shù)writeMsgToClient函數(shù)結束")
}

// 添加新用戶
func addUser(conn net.Conn) client {
	fmt.Println("開始使用添加新用戶" + conn.RemoteAddr().String())
	newUser := client{
		make(chan string), // 創(chuàng)建用戶消息通道
		conn,              // 網(wǎng)絡連接
		conn.RemoteAddr().String(), // 用戶名,初始化為客戶端地址
		conn.RemoteAddr().String(), // 客戶端地址
	}
	onlineList[conn.RemoteAddr().String()] = &newUser // 添加到在線用戶列表

	fmt.Println("addUser函數(shù)結束,用戶" + conn.RemoteAddr().String() + "添加成功")
	return newUser
}

// 讀取客戶端消息的協(xié)程
func readClient(conn net.Conn, quit chan bool) {
	fmt.Println("開始讀取客戶端發(fā)送的信息")
	defer fmt.Println("客戶端發(fā)送信息讀取結束")

	userChannel := onlineList[conn.RemoteAddr().String()].userChannel

	reader := bufio.NewReader(conn)
	for {
		msg, err := module.Decode(reader)
		if err == io.EOF {
			quit <- true
		}
		if err != nil {
			fmt.Println("decode msg failed, err:", err)
			quit <- true
		}
		if len(msg) == 0 {
			continue
		}
		fmt.Println("收到client發(fā)來的數(shù)據(jù):", msg)

		// 處理客戶端發(fā)送的不同類型的消息
		switch {
		case strings.HasPrefix(msg, "!@#$@!cd1changeName"):

			king := true
			oldName := onlineList[conn.RemoteAddr().String()].name
			newName := strings.TrimPrefix(msg, "!@#$@!cd1changeName")

			if strings.HasPrefix(msg, "!@#$@!cd1changeNameFirst") {
				newName = strings.TrimPrefix(msg, "!@#$@!cd1changeNameFirst")
			}

			if newName == "" {
				newName = conn.RemoteAddr().String()
			}

			for _, v := range onlineList {

				mapName := v.name
				if mapName == newName {

					king = false

					break
				}
			}

			if strings.HasPrefix(msg, "!@#$@!cd1changeNameFirst") && king == false {

				message <- "< 系統(tǒng)消息 > [ " + conn.RemoteAddr().String() + " ] [ " + oldName + " ] 上線了!"

				userChannel <- "< 系統(tǒng)消息 > [ " + onlineList[conn.RemoteAddr().String()].name + " ]" + "名字: " + newName + " 已存在,請更換一個名字嘗試"

				userChannel <- "< 系統(tǒng)消息 > 你當前昵稱為: " + oldName + " ( 輸入cd2可進行名字修改 )"

				continue
			}

			if king == false {

				userChannel <- "< 系統(tǒng)消息 > 昵稱修改失?。。?!"

				userChannel <- "< 系統(tǒng)消息 > [ " + onlineList[conn.RemoteAddr().String()].name + " ]" + "名字: " + newName + " 已存在,請更換一個名字嘗試"

				userChannel <- "< 系統(tǒng)消息 > 你當前昵稱為: " + oldName

				continue

			}

			isSuccess := onlineList[conn.RemoteAddr().String()].changeName(newName)
			if isSuccess {

				userChannel <- "!@#$@!cd1changeName" + newName

				if strings.HasPrefix(msg, "!@#$@!cd1changeNameFirst") {

					message <- "< 系統(tǒng)消息 > [ " + conn.RemoteAddr().String() + " ] [ " + newName + " ] 上線了!"

					time.Sleep(time.Millisecond * 50)

					userChannel <- "< 系統(tǒng)消息 > 你當前的昵稱為:" + newName

					continue
				}

				userChannel <- "< 系統(tǒng)消息 > 昵稱修改成功 你當前昵稱為: " + newName

			} else {

				userChannel <- "< 系統(tǒng)消息 > 昵稱修改失?。。?!"

			}

			message <- "< 系統(tǒng)消息 > [ " + conn.RemoteAddr().String() + " ]" + " 舊昵稱為: " + oldName + " 新昵稱為: " + newName

		case strings.HasPrefix(msg, "!@#$@!cd4exit"):
			fmt.Println("[ " + onlineList[conn.RemoteAddr().String()].name + " ] " + "下線了")

			quit <- true

			return
		case strings.HasPrefix(msg, "!@#$@!menu"):

			userChannel <- "< 系統(tǒng)消息 > \n * ./cd1 或 ./menu       功能菜單\n * ./cd2 或 ./changeName 更改昵稱\n * ./cd3 或 ./online     在線用戶數(shù)量查詢\n * ../cd4 或 ./quit      退出聊天室"

		case strings.HasPrefix(msg, "!@#$@!cd3online"):

			fmt.Println("在線人數(shù):", count)

			userChannel <- "< 系統(tǒng)消息 > 當前在線人數(shù):" + strconv.Itoa(count)

		default:

			message <- "[ " + onlineList[conn.RemoteAddr().String()].name + " ]" + ": " + msg

			fmt.Println("信息廣播成功")
		}
	}
}

客戶端

基本流程

1. 主函數(shù) main()

  • 嘗試連接到服務器 "127.0.0.1:8080"。
  • 如果連接失敗,打印錯誤信息并退出程序。
  • 如果連接成功,獲取用戶的昵稱并發(fā)送給服務器。
  • 創(chuàng)建一個 exit 通道,用于接收退出信號。
  • 打印歡迎信息和命令提示。
  • 啟動一個協(xié)程 readMsg(conn) 用于讀取消息。
  • 啟動另一個協(xié)程用于處理用戶輸入。
  • 主循環(huán)中監(jiān)聽 exit 通道,如果接收到信號則退出程序。

2. 獲取用戶輸入 getUserInput(prompt string)

  • 根據(jù)傳入的提示信息顯示相應的提示。
  • 讀取用戶從標準輸入的輸入。
  • 返回去除空白字符的輸入字符串。

3. 讀取消息 readMsg(conn)

  • 從服務器讀取消息。
  • 如果讀取到 EOF (文件結束),則表示服務器連接已斷開,終止程序。
  • 如果讀取過程中出現(xiàn)其他錯誤,則打印錯誤信息并退出函數(shù)。
  • 如果接收到的消息為空,則跳過本次循環(huán)。
  • 如果接收到的消息是以 !@#$@!cd1changeName 開頭,則更新用戶的昵稱。
  • 打印接收到的消息的時間戳和內容。

4. 處理用戶輸入

  • 循環(huán)讀取用戶輸入,并根據(jù)不同的命令構建消息。
  • 如果命令是 ./cd1 或 ./menu,則發(fā)送 !@#$@!menu 消息。
  • 如果命令是 ./cd2 或 ./changeName,則請求用戶輸入新的昵稱,并發(fā)送 !@#$@!cd1changeName 加上新的昵稱。
  • 如果命令是 ./cd3 或 ./online,則發(fā)送 !@#$@!cd3online 消息。
  • 如果命令是 cd4 或 ./quit,則發(fā)送 !@#$@!cd4exit 消息,并發(fā)送退出信號到 exit 通道。
  • 對于其他消息,編碼并發(fā)送到服務器。

代碼

package main

import (
	"bufio"         
	"chatRoom/chatRoom/module" // 消息的編碼和解碼模塊
	"fmt"            
	"io"            
	"net"            
	"os"            
	"strings"        
	"time"           
)

// 定義一個全局變量用于存儲用戶的昵稱
var name string

// 主函數(shù)
func main() {
	// 嘗試連接到服務器
	conn, err := net.Dial("tcp", "127.0.0.1:8080")
	if err != nil {
		fmt.Println("服務器連接失敗 err =", err)
		return
	}

	defer conn.Close()
	// 打印連接成功的消息
	fmt.Println("服務器連接成功")

	// 獲取用戶的昵稱
	name = getUserInput("請輸入你的昵稱:")
	// 構建一條特殊的消息,用于通知服務器用戶昵稱
	data, err := module.Encode("!@#$@!cd1changeNameFirst" + name)
	if err != nil {
		
		fmt.Println("encode msg failed, err:", err)
		return
	}
	// 發(fā)送消息到服務器
	_, err = conn.Write(data)
	if err != nil {
		fmt.Println("發(fā)送數(shù)據(jù)失敗1 err =", err)
	}

	// 創(chuàng)建一個通道,用于接收退出信號
	var exit = make(chan bool)
	// 確保在函數(shù)退出時關閉通道
	defer close(exit)

	// 顯示歡迎信息和命令提示
	fmt.Println("--------------歡迎進入多人聊天室系統(tǒng)----------------")
	fmt.Println("       * ./cd1 或 ./menu       功能菜單")
	fmt.Println("       * ./cd2 或 ./changeName 更改昵稱")
	fmt.Println("       * ./cd3 或 ./online     在線用戶數(shù)量查詢")
	fmt.Println("       * ./cd4 或 ./quit       退出聊天室")
	fmt.Println("---------------指令字母不區(qū)分大小寫-----------------")

	// 啟動一個協(xié)程用于讀取消息
	go readMsg(conn)

	// 啟動一個協(xié)程用于處理用戶輸入
	go func() {
		for {
			// 獲取用戶輸入
			msg := getUserInput("")

			// 根據(jù)用戶輸入特殊消息處理命令
			if strings.EqualFold(msg, "./cd1") || strings.EqualFold(msg, "./menu") {
				msg = "!@#$@!menu"
			}
			if strings.EqualFold(msg, "./cd2") || strings.EqualFold(msg, "./changeName") {
				newMsg := getUserInput("請輸入新的昵稱:")
				msg = "!@#$@!cd1changeName" + newMsg
			}
			if strings.EqualFold(msg, "./cd3") || strings.EqualFold(msg, "./online") {
				msg = "!@#$@!cd3online"
			}
			if strings.EqualFold(msg, "./cd4") || strings.EqualFold(msg, "./quit") {
				msg = "!@#$@!cd4exit"
				// 編碼并發(fā)送退出消息
				data, err := module.Encode(msg)
				if err != nil {
					fmt.Println("消息數(shù)據(jù)失敗1, err:", err)
					return
				}
				_, err = conn.Write(data)
				if err != nil {
					// 如果發(fā)送失敗,打印錯誤信息
					fmt.Println("發(fā)送數(shù)據(jù)失敗2 err =", err)
				}
				// 打印退出信息
				fmt.Println("正在退出...")
				// 發(fā)送退出信號
				exit <- true
				return
			}

			// 編碼并發(fā)送普通消息
			data, err := module.Encode(msg)
			if err != nil {
				// 如果消息編碼失敗,打印錯誤信息并退出協(xié)程
				fmt.Println("發(fā)送數(shù)據(jù)失敗3, err:", err)
				return
			}
			_, err = conn.Write(data)
			if err != nil {
				// 如果發(fā)送失敗,打印錯誤信息
				fmt.Println("發(fā)送數(shù)據(jù)失敗4 err =", err)
			}
		}
	}()

	// 主循環(huán),監(jiān)聽退出信號
	for {
		select {
		case <-exit:
			// 當收到退出信號時,打印退出成功并退出程序
			fmt.Println("退出成功")
			return
		}
	}
}

// getUserInput 函數(shù)用于獲取用戶輸入
func getUserInput(prompt string) string {

	time.Sleep(time.Millisecond * 100)
	// 根據(jù)不同的提示信息顯示相應的提示
	switch prompt {
	case "請輸入你的昵稱:":
		fmt.Print("請輸入你的昵稱:")
	case "請輸入新的昵稱:":
		fmt.Println("請輸入新的昵稱:")
	}
	// 創(chuàng)建一個標準輸入的緩沖讀取器
	reader := bufio.NewReader(os.Stdin)
	// 讀取一行輸入
	input, err := reader.ReadString('\n')
	if err != nil {
		// 如果讀取失敗,打印錯誤信息并返回錯誤信息
		fmt.Println("用戶輸入獲取失敗:err =", err)
		return "客戶端信息讀取錯誤"
	}
	// 返回去掉空格的輸入字符串
	return strings.TrimSpace(input)
}

// readMsg 函數(shù)用于讀取消息
func readMsg(conn net.Conn) {

	defer conn.Close()
	// 創(chuàng)建一個緩沖讀取器來讀取連接中的數(shù)據(jù)
	reader := bufio.NewReader(conn)
	for {
		// 解碼消息
		msg, err := module.Decode(reader)
		if err == io.EOF {
			// 如果遇到EOF(文件結束),表示連接已斷開
			fmt.Println("服務器連接已斷開 ")
			// 終止程序
			os.Exit(1)
		}
		if err != nil {
		
			fmt.Println("服務器斷開連接 2 err =", err)
			return
		}
		if msg == "" {
			// 如果消息為空,則跳過本次循環(huán)
			continue
		}
		if strings.HasPrefix(msg, "!@#$@!cd1changeName") {
			// 如果消息是更改昵稱的通知
			msg1 := strings.TrimPrefix(msg, "!@#$@!cd1changeName")
			name = strings.TrimRight(msg1, "\n")
			// 更新昵稱
			continue
		}
		// 打印消息的時間戳和內容
		fmt.Print("【 ", time.Now().Format("15:04"), " 】", msg)
	}
}

消息封包和解包的函數(shù)

作用:防止tcp粘包的情況影響消息的讀取

1.為什么會出現(xiàn)粘包

主要原因就是tcp數(shù)據(jù)傳遞模式是流模式,在保持長連接的時候可以進行多次的收和發(fā)。

“粘包"可發(fā)生在發(fā)送端也可發(fā)生在接收端:

  • 由Nagle算法造成的發(fā)送端的粘包:Nagle算法是一種改善網(wǎng)絡傳輸效率的算法。簡單來說就是當我們提交一段數(shù)據(jù)給TCP發(fā)送時,TCP并不立刻發(fā)送此段數(shù)據(jù),而是等待一小段時間看看在等待期間是否還有要發(fā)送的數(shù)據(jù),若有則會一次把這兩段數(shù)據(jù)發(fā)送出去。
  • 接收端接收不及時造成的接收端粘包:TCP會把接收到的數(shù)據(jù)存在自己的緩沖區(qū)中,然后通知應用層取數(shù)據(jù)。當應用層由于某些原因不能及時的把TCP的數(shù)據(jù)取出來,就會造成TCP緩沖區(qū)中存放了幾段數(shù)據(jù)。

2.解決辦法

出現(xiàn)"粘包"的關鍵在于接收方不確定將要傳輸?shù)臄?shù)據(jù)包的大小,因此我們可以對數(shù)據(jù)包進行封包和拆包的操作。

封包:封包就是給一段數(shù)據(jù)加上包頭,這樣一來數(shù)據(jù)包就分為包頭和包體兩部分內容了(過濾非法包時封包會加入"包尾"內容)。包頭部分的長度是固定的,并且它存儲了包體的長度,根據(jù)包頭長度固定以及包頭中含有包體長度的變量就能正確的拆分出一個完整的數(shù)據(jù)包。

我們可以自己定義一個協(xié)議,比如數(shù)據(jù)包的前4個字節(jié)為包頭,里面存儲的是發(fā)送的數(shù)據(jù)的長度。

代碼

package module

import (
	"bufio"
	"bytes"
	"encoding/binary"
)

func Encode(message string) ([]byte, error) {
	// 讀取消息的長度,轉換成int32類型(占4個字節(jié))
	var length = int32(len(message))
	var pkg = new(bytes.Buffer)
	// 寫入消息頭
	err := binary.Write(pkg, binary.LittleEndian, length)
	if err != nil {
		return nil, err
	}
	// 寫入消息實體
	err = binary.Write(pkg, binary.LittleEndian, []byte(message))
	if err != nil {
		return nil, err
	}
	return pkg.Bytes(), nil
}

// Decode 解碼消息
func Decode(reader *bufio.Reader) (string, error) {
	// 讀取消息的長度
	lengthByte, _ := reader.Peek(4) // 讀取前4個字節(jié)的數(shù)據(jù)
	lengthBuff := bytes.NewBuffer(lengthByte)
	var length int32
	err := binary.Read(lengthBuff, binary.LittleEndian, &length)
	if err != nil {
		return "", err
	}
	// Buffered返回緩沖中現(xiàn)有的可讀取的字節(jié)數(shù)。
	if int32(reader.Buffered()) < length+4 {
		return "", err
	}

	// 讀取真正的消息數(shù)據(jù)
	pack := make([]byte, int(4+length))
	_, err = reader.Read(pack)
	if err != nil {
		return "", err
	}
	return string(pack[4:]), nil
}

以上就是基于Go語言實現(xiàn)簡單網(wǎng)絡聊天室(命令行模式)的詳細內容,更多關于Go聊天室的資料請關注腳本之家其它相關文章!

相關文章

  • 分析Go錯誤處理優(yōu)化go?recover機制缺陷

    分析Go錯誤處理優(yōu)化go?recover機制缺陷

    這篇文章主要為大家介紹了分析Go錯誤處理優(yōu)化go?recover機制缺陷示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • Go unsafe 包的使用詳解

    Go unsafe 包的使用詳解

    這篇文章主要介紹了Go unsafe 包的使用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-01-01
  • 淺析Go語言中的超時控制

    淺析Go語言中的超時控制

    日常開發(fā)中我們大概率會遇到超時控制的場景,而一個良好的超時控制可以有效的避免一些問題,所以本文就來和大家深入探討一下Go語言中的超時控制吧
    2023-10-10
  • Go 基于令牌桶的限流器實現(xiàn)

    Go 基于令牌桶的限流器實現(xiàn)

    如果一般流量過大,下游系統(tǒng)反應不過來,這個時候就需要限流了,本文主要介紹了Go 基于令牌桶的限流器實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Go打印結構體提升代碼調試效率實例詳解

    Go打印結構體提升代碼調試效率實例詳解

    這篇文章主要介紹了Go打印結構體提升代碼調試效率實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-02-02
  • GoLang協(xié)程庫libtask學習筆記

    GoLang協(xié)程庫libtask學習筆記

    libtask一個C語言的協(xié)程庫,是go語言的前身很早期的原型. 測試機器是我的mac air 安裝的centos虛擬機(只有一個核), 代碼沒有采用任何優(yōu)化,只是使用默認配置
    2022-12-12
  • 盤點總結2023年Go并發(fā)庫有哪些變化

    盤點總結2023年Go并發(fā)庫有哪些變化

    這篇文章主要為大家介紹了2023年Go并發(fā)庫的變化盤點總結,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • golang中使用匿名結構體的方法

    golang中使用匿名結構體的方法

    這篇文章主要介紹了golang中使用匿名結構體,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08
  • Gin使用swagger生成接口文檔的代碼示例

    Gin使用swagger生成接口文檔的代碼示例

    Swagger 是一個規(guī)范和完整的框架,用于生成、描述、調用和可視化 RESTful Web 服務,它使用 YAML 或 JSON 格式來定義 API 的結構,本文給大家介紹了Gin使用swagger生成接口文檔的代碼示例,需要的朋友可以參考下
    2024-06-06
  • Golang使用ini庫讀取配置詳情

    Golang使用ini庫讀取配置詳情

    這篇文章主要介紹了Golang使用ini庫讀取配置詳情,go-ini是一個非常方便、高效的go配置文件操作庫。使用它在項目中讀取和修改配置文件,下文相關資料需要的小伙伴可可以參考一下
    2022-04-04

最新評論

孙吴县| 黑水县| 炎陵县| 宁夏| 建水县| 大英县| 蒲江县| 班戈县| 汤原县| 博罗县| 开鲁县| 成安县| 南华县| 凤城市| 潼南县| 佛冈县| 静乐县| 开江县| 鄂伦春自治旗| 南昌县| 商河县| 西昌市| 洞头县| 江安县| 法库县| 洛浦县| 五家渠市| 九龙城区| 泰和县| 会同县| 措美县| 南和县| 岐山县| 长阳| 井研县| 大竹县| 曲松县| 赣榆县| 木兰县| 铅山县| 新乐市|