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

你可能感兴趣的:(GO 中byte、uint8、uint32 转换、左移、右移)