日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Golang常用包使用介紹_Golang

作者:whynogome ? 更新時間: 2022-11-06 編程語言

sync包

常用的有3個功能

鎖分為普通互斥鎖和讀寫鎖

互斥鎖 Mutex 讀寫鎖 RWMutex
一個線程未釋放鎖時,其他線程加鎖阻塞 讀鎖:一個線程未釋放讀鎖時,其他線程可獲取讀鎖,獲取寫鎖阻塞
寫鎖:一個線程未釋放寫鎖時,其他線程可獲取讀鎖或寫鎖都會阻塞

線程監聽WaitGroup

使用場景:用于監聽一組子線程是否執行完畢

使用流程 代碼
建立監聽對象 wg := new(sync.WaitGroup)
創建多個子線程并計入計數器 go func1(wg)
wg.Add(1)
go func2(wg)
wg.Add(1)
線程子線程執行完畢后,減少計數器值 func1(wg){wg.Done()}
監聽計數器值,直到計數器值為0時,執行后面的代碼 wg.Wait()

池Pool

用于存放每次請求都需要實例化,且生命周期較長的對象,以減輕垃圾回收壓力。

使用流程 代碼
建立一個池 RequestPool = sync.Pool{New: func() interface{} {return &RequestHeader{}}}
從池中取一個對象 RequestPool .Get()
把對象放回池中 RequestPool .Put(RequestHeader)
把對象放入池之前,需要把對象中所有值都初始化

encoding/binary包

主要用來把數字轉換為字節類型

單數值轉換

//序列化
    var dataA uint64=6010
    var buffer bytes.Buffer
    err1 := binary.Write(&buffer, binary.BigEndian, &dataA)
    if err1!=nil{
        log.Panic(err1)
    }
    byteA:=buffer.Bytes()
    fmt.Println("序列化后:",byteA)
    //反序列化
    var dataB uint64
    var byteB []byte=byteA
    err2:=binary.Read(bytes.NewReader(byteB),binary.BigEndian,&dataB)
    if err2!=nil{
        log.Panic(err2)
    }
    fmt.Println("反序列化后:",dataB)

其中的BigEndian和LittleEndian 指定了轉換的方式是 大端字節序,還是小端字節序。

所謂大端和小端節序,是指不同cpu再把數據流轉換為字節時,排位位置的不同,如下

若不同計算機程序之間使用了不同節序處理同一組數據,就會造成無法解析的情況

多數值轉換

指把多個數字轉換到一個byte切片中

首先定義一個定長切片 s := make([]byte,10)

首先要確定轉換的節序,也可以跳過該步驟

binary.LittleEndian.PutUint16(s, uint16(0))

確定完之后,就可以向s中插入數字了

start := 0
start += binary.PutUvarint(b[2:], 1198)

插入數字到切片后,會返回該數字在切片中占用的長度

若切片空間不夠,則返報錯

所以我們最好確定往切片中插入數字的個數,并估算每個數字占用最大占用長度

解析切片中的某個數字,要知道該數字在切片中占用的起始位置,若位置不對則無法解析出正確的數字,返回0

i,err := binary.ReadUvarint(bytes.NewReader(b[2:]))
if err==nil{
   fmt.Println(i)
}else{
   fmt.Println(err.Error())
} 		

切片中可以插入字符串,轉換為數字時,只要能夠從正確的位置開始解析,就會解析出正確的數字

encoding/gob包

是一個golang專屬的數據序列化工具,用于序列化和反序列化數據,作用類似于json

不同的是,在反序列化時,需要有一個指定格式的變量接收值。該變量類型需要與序列化時數據類型兼容,否則反序列化失敗

	type S struct{
		Field1 string
		Field2 int
    }
	func main() {
		s1 := &S{
			Field1: "Hello Gob",
			Field2: 999,
		}
		log.Println("Original value:", s1)
		buf := new(bytes.Buffer)
		err := gob.NewEncoder(buf).Encode(s1)
		if err != nil {
			log.Println("Encode:", err)
			return
		}
		s2 := &S{}
		err = gob.NewDecoder(buf).Decode(s2)
		if err != nil {
			log.Println("Decode:", err)
			return
		}
		log.Println("Decoded value:", s2)
	}

簡單的數據可以使用上面代碼直接加密和解密

但是當需要解密的數據是接口類型時,由于接口的特殊性,實現了接口中方法的變量可以作為值代替該方法,這導致gob不知道接口中數據的具體類型,會解密失敗,如下

type Getter interface {
    Get() string
}
type Foo struct {
    Bar string
}
func (f Foo)Get() string {
    return f.Bar
}
buf := bytes.NewBuffer(nil)
// 創建一個接口變量
//接口中原值是一個get方法,因為Foo實現了get方法,所以可以最為值代替Get
g := Getter(Foo{"wazzup"})
// gob解密g時,認為g中的值是Get() 類型,但其實是Foo類型,就會報錯
enc := gob.NewEncoder(buf)
enc.Encode(&g)

解決這個問題的方法就是在代碼初始化時,使用 gob.Register()方法注冊Foo變量

當gob解碼是發現類型不對應,會從已注冊的類型中查找

hash/crc32包

常用方法:

func ChecksumIEEE(data []byte) uint32

返回數據data使用IEEE多項式計算出的CRC-32校驗和

可通過對比數據發送和接收時的校驗和,驗證數據是否被篡改

原文鏈接:https://blog.csdn.net/u012830303/article/details/126485652

欄目分類
最近更新