go實用小技能(四)-int類型轉成byte類型原理解密

咱們在進行網絡編程的時候,都會遇到大小端模式的問題。剛開始接觸的時候我也比較懵逼,大端小端,什麼鬼?網上說的不少術語都看不明白。其實按照我我的的理解,大端模式就是和咱們閱讀現代文學同樣,通常都是從左到右進行閱讀。而小端模式就像在閱讀古代的武功祕籍同樣,是從右往左進行學習的。java

固然我今天不會去講爲何存在大小端這種不一樣的模式,只要在咱們進行int和byte進行互轉的時候,知道有這麼個概念就能夠了。git

在go語言中的byte的存儲方式和java的不同。java的byte是有符號的,而go的byte是使用無符號進行存儲的。經過查看go源代碼咱們知道byte實際上是uint8的別名,也就是說byte在存儲的時候佔用了8個比特,byte和uint8之間不須要任何的操做就能夠直接進行互轉。github

// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is // used, by convention, to distinguish byte values from 8-bit unsigned // integer values. type byte byte編程

接下來一步一步去驗證剛剛咱們的推理是否正確。首先咱們知道uint8取值範圍是0~255,那麼咱們先將0~255這個範圍的int轉成byte數組

func f1() {
	var v1 uint32
	v1 = 255
	fmt.Println(byte(v1))
}

上面的代碼運行結果爲:255,和咱們想的是同樣的,byte 和 uint8 之間能夠直接進行互轉。目前來只能將0~255範圍的int轉成byte。由於超出這個範圍,go在轉換的時候,就會把多出來數據扔掉。網絡

如今得想個辦法將大於255的數字轉成byte可接受的範圍?學習

聰明的小夥伴應該想到了。一個byte只能放255,若是超過255再加一個byte不就好了。^>^ 沒錯,其實咱們可使用[]byte數組來解決這個問題。一個byte最大值255,表示成二進制就是:1111 1111。兩個byte最大值爲65535,表示成二進制就是:1111 1111 1111 1111,兩個byte恰好佔16比特和uint16同樣。同理。三個byte最大值爲:16777215, 表示成二進制就是:1111 1111 1111 1111 1111 1111。四個byte就是4294967295,二進制表示爲:1111 1111 1111 1111 1111 1111 1111 1111。ui

經過上面分析能夠得出,若是須要將int32轉成byte類型,咱們只須要一個長度爲4的[]byte數組就能夠了,如今還有最後一個難點就是對int數據進行拆分。將0~255區間的數據放在下標爲3的位置。將256~65535區間的數據放在下標爲2的位置,將65536~16777215區間的數據放在下標爲1的位置,將16777216~4294967295區間的數據放在下標爲0的位置。這裏可能比較暈,下面直接看代碼可能就會明白了code

// 這裏是大端模式
func f2() {
	var v2 uint32
	var b2 [4]byte
	v2 = 257
	// 將 256轉成二進制就是
	// | 00000000 | 00000000 | 00000001 | 00000001 |
	// | b2[0]    | b2[1]   | b2[2]    | [3]      | // 這裏表示b2數組每一個下標裏面存放的值

	// 這裏直接使用將uint32l強轉成uint8
	// | 00000000 0000000 00000001 | 00000001  直接轉成uint8後等於 1
	// |---這部分go在強轉的時候扔掉---|
	b2[3] = uint8(v2)

	// | 00000000 | 00000000 | 00000001 | 00000001 | 右移8位 轉成uint8後等於 1
	// 下面是右移後的數據
	// |          | 00000000 | 00000000 | 00000001 |
	b2[2] = uint8(v2 >> 8)

	// | 00000000 | 00000000 | 00000001 | 00000001 | 右移16位 轉成uint8後等於 0
	// 下面是右移後的數據
	// |          |          | 00000000 | 00000000 |
	b2[1] = uint8(v2 >> 16)

	// | 00000000 | 00000000 | 00000001 | 00000001 | 右移24位 轉成uint8後等於 0
	// 下面是右移後的數據
	// |          |          |          | 00000000 |
	b2[0] = uint8(v2 >> 24)

	fmt.Printf("%+v\n", b2)
	// 因此最終將uint32轉成[]byte數組輸出爲
	// [0 0 1 1]
}

// 這裏是小端模式
// 在上面咱們講過,小端恰好和大端相反的,因此在轉成小端模式的時候,只要將[]byte數組的下標首尾對換一下位置就能夠了
func f3() {
	var v3 uint32
	var b3 [4]byte
	v3 = 257
	// 將 256轉成二進制就是
	// | 00000000 | 00000000 | 00000001 | 00000001 |
	// | b3[0]    | b3[1]   | b3[2]    | [3]      | // 這裏表示b3數組每一個下標裏面存放的值

	// 這裏直接使用將uint32l強轉成uint8
	// | 00000000 0000000 00000001 | 00000001  直接轉成uint8後等於 1
	// |---這部分go在強轉的時候扔掉---|
	b3[0] = uint8(v3)

	// | 00000000 | 00000000 | 00000001 | 00000001 | 右移8位 轉成uint8後等於 1
	// 下面是右移後的數據
	// |          | 00000000 | 00000000 | 00000001 |
	b3[1] = uint8(v3 >> 8)

	// | 00000000 | 00000000 | 00000001 | 00000001 | 右移16位 轉成uint8後等於 0
	// 下面是右移後的數據
	// |          |          | 00000000 | 00000000 |
	b3[2] = uint8(v3 >> 16)

	// | 00000000 | 00000000 | 00000001 | 00000001 | 右移24位 轉成uint8後等於 0
	// 下面是右移後的數據
	// |          |          |          | 00000000 |
	b3[3] = uint8(v3 >> 24)

	fmt.Printf("%+v\n", b3)
	// 因此最終將uint32轉成[]byte數組輸出爲
	// [1 1 0 0 ]
}

示例代碼下載地址:https://github.com/wuciyou/blog/tree/master/go-%E5%AE%9E%E7%94%A8%E5%B0%8F%E6%8A%80%E8%83%BD/int%E5%92%8Cbyte%E8%BF%9B%E8%A1%8C%E4%BA%92%E8%BD%AC%E5%8E%9F%E7%90%86%E8%A7%A3%E5%AF%86blog

dogo 技術交流羣:437274005

歡迎加入 dogo 技術交流羣:437274005 點擊右側按鈕快捷加入 dogo交流羣

相關文章
相關標籤/搜索