GO 中byte、uint8、uint32 转换、左移、右移

概念

go默认使用Unicode字符集,同时使用utf-8作为编码方式
go里面没有字符类型(char),而是使用byte(uint8)和rune(int32)来代表字符。
我们声明一个字符时,默认是rune类型,除非特别定义。 一个string变量既可以被拆分为字符,也可以被拆分为字节;前者使用rune[]切片表示,后者使用byte[]切片表示
一个rune值就是代表一个字符,在输入输出中经常看到类似’\U0001F3A8’,’\u2665’的就是一个rune字符(unicode字符),其中的每位都是一个16进制数

var a = 'A'  // rune type
var b byte = 'a'  // byte type
c:= byte('b')  // byte type

本质上,byte其实都是整型类型,其中byte是uint8的别称,rune是int32的别称。例如一个byte类型的字符'a'其实是整型数字97,对应ASCII码的字符a。

var a = 'a'
var b byte = 'a'

fmt.Printf("%T, %v", a, a)  // int32, 97
fmt.Printf("%T, %v", b, b)  // uint8, 97

byte类型和rune类型使用编码方式不同,其中byte是ASCII编码字符,rune是utf-8字符。

string
字符串可以为空,但不能为nil;
字符串的值不能修改,只能替换;
修改字符串时需要重新分配一次内存,之前分配的内存由gc回收(因此字符串比较低效)

[]byte字符串
[]byte字符串类型适用于字符串的拼接:

byte 字符
[]byte 字符串
[][]byte字符串数组
    b1 := byte('a')  // 字符
    b2 := []byte("A")  // 字符串
    b3 := []byte{'a', 'b', 'c'}  // 字符串
    fmt.Printf("b1 = %c\n", b1)
    fmt.Printf("b2 = %c\n", b2)
    fmt.Printf("b3 = %s\n", b3)
    s1 := []byte("Hello")  // 字符串
    s2 := []byte("World")  // 字符串
    s3 := [][]byte{s1, s2}  // 字符串数组
    s4 := bytes.Join(s3, []byte(","))
    s5 := []byte{}
    s5 = bytes.Join(s3, []byte("--"))
    s6 := [][]byte{[]byte("foo"), []byte("bar"), []byte("baz")}
    fmt.Printf("s1 = %s\n", s1)
    fmt.Printf("s2 = %s\n", s2)
    fmt.Printf("s3 = %s\n", s3)
    fmt.Printf("s4 = %s\n", s4)
    fmt.Printf("s5 = %s\n", s5)
    fmt.Printf("%s\n", bytes.Join(s6, []byte(", ")))
b1 = a
b2 = [A]
b3 = abc
s1 = Hello
s2 = World
s3 = [Hello World]
s4 = Hello,World
s5 = Hello--World
foo, bar, baz

String和[]byte转换及使用场景

转换

// string to []byte
s1 := "hello"
b := []byte(s1)

// []byte to string
s2 := string(b)

使用场景
需要用做map的key时,用string,因为string可以直接比较,[]byte不可以
如果需要用nil来表示额外的含义,用[]byte,因为string不能取nil值,[]byte可以

————————————————
版权声明:本文为CSDN博主「AXIMI」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/AXIMI/article/details/120379225

C语言中什么叫做高八位和低八位啊?

高八位和低八位:内存里,一个单元是一个字节,也就是8位。如果是16位的指令,就是同时操作连续的2个内存地址,将这连续的2个内存地址当成一个单位,所以就有高8位和低8位之分。

由于计算机仅识别二进制描述的数字,所以对一个内存地址,也就是8位二进制,如:0000 0001,0000就是高四位,0001就是低四位。

当然2个内存地址,就是16位二进制,也就是:0000 0001 0000 0002。0000 0001 就是高八位,0000 0002就是低八位。

每个八位中又分成高低四位。如:1010 0001 1111 0101,换算成16进制就是:1010–10(10进制)—A(16进制),0001–1(10进制)—1(16进制)所以他的高八位就是A1,同样它的低八位就是F5。

扩展资料:

如何在C语言中的ascII码表里查找高四位、低四位:

ascii码在C语言中用char型存储,一个char占一个字节,即8位。

当写成二进制表达形式时,就是8个0或者1的数字,这8个数字中,左边四个称为高四位,右边四个称为低四位。

所以在查ascii码表时,需要:

1、把要查的值,转成二进制值;

2、得到高四位值,及低四位值;
3、根据高四位值查表,找到所在列;

4、根据低四位值查表,找到所在行;

5、所在行列的交叉格,就是要查找的字符。

主机字节序

主机字节序模式有两种,大端数据模式和小端数据模式,在网络编程中应注意这两者的区别,以保证数据处理的正确性;例如网络的数据是以大端数据模式进行交互,而我们的主机大多数以小端模式处理,如果不转换,数据会混乱 参考 ;一般来说,两个主机在网络通信需要经过如下转换过程:主机字节序 —> 网络字节序 -> 主机字节序

大端小端区别

大端模式:Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端
低地址 --------------------> 高地址
高位字节 地位字节
小端模式:Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端
低地址 --------------------> 高地址
低位字节 高位字节

什么是高位字节和低位字节

例如在32位系统中,357转换成二级制为:00000000 00000000 00000001 01100101,其中

00000001 | 01100101
高位字节 低位字节

int和byte转换

go语言中,byte其实是uint8的别名,byte 和 uint8 之间可以直接进行互转。目前来只能将0~255范围的int转成byte。因为超出这个范围,go在转换的时候,就会把多出来数据扔掉;如果需要将int32转成byte类型,我们只需要一个长度为4的[]byte数组就可以了

大端模式下

func f2() {
    var v2 uint32
    var b2 [4]byte
    v2 = 257

    // 将 257转成二进制就是
    // | 00000000 | 00000000 | 00000001 | 00000001 |
    // | b2[0]    | b2[1]    | b2[2]    | b2[3]    | // 这里表示b2数组每个下标里面存放的值
    // 这里直接使用将uint32强转成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 ]
}

go转换demo
案例1

//整形转换成字节
func IntToBytes(n int) []byte {
  x := int32(n)
  bytesBuffer := bytes.NewBuffer([]byte{})
  binary.Write(bytesBuffer, binary.BigEndian, x)
  return bytesBuffer.Bytes()
}
//字节转换成整形
func BytesToInt(b []byte) int {
  bytesBuffer := bytes.NewBuffer(b)

  var x int32
  binary.Read(bytesBuffer, binary.BigEndian, &x)

  return int(x)
}

案例2

arg := uint32(115)
bytes := make([]byte, 4)
binary.BigEndian.PutUint32(bytes,  arg)

源码

func (bigEndian) PutUint32(b []byte, v uint32) {
    _ = b[3] // early bounds check to guarantee safety of writes below
    b[0] = byte(v >> 24)
    b[1] = byte(v >> 16)
    b[2] = byte(v >> 8)
    b[3] = byte(v)
}

相关面试题

1.mysql 中int(11)最大最小存储多少

        | tinyint | smallint | mediumint | int | bigint | 
        | 1       | 2        | 3         | 4   | 8      |  占用字节

1字节(Byte)占8个位(bit),1个位表示一个二进制的0或者1,
1个字节能表示最大的整数是255,怎么来的?
1个字节就是8个二进制的1  “11111111” 转换成十进制就是255
1*2^7+1*2^6+1*2^5+1*2^4+1*2^3+1*2^2+1*2^1+1*2^0=255

int 占用4个字节 1个字节是8个位(bit) 即等于32个位(bit)

有符号 int 取值范围 等于int8  的取值范围 详见下面附属表2.取值范围
-2^31 (-2,147,483,648) 到 2^31 - 1 (2,147,483,647) 
无符号 int 取值范围 等于uint8 的取值范围 详见下面附属表2.取值范围
0 到 (2^32)  - 1 (4,294,967,295) 

tinyint | smallint | mediumint | int | bigint 计算一样参考

关于int(11)中的(11)是mysql 中选择是否填充时使用
当设置填充是假设存储值1 表中则显示为: 00000000001
当不设置填充是假设存储值1 表中则显示为: 1

扩展资料

int类型, 占用字节数为4byte, 学过计算机原理的同学应该知道,字节(byte)并非是计算机存储的最小单位,
还有比字节(byte)更小的单位,也就是位(bit),一个位就代表一个0或1; 8个位组成一个字节;一般字节用大写B来表示byte,位用小写b来表示bit。

附属表1.ASCII码表


image.png

附属表2.取值范围


image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容