Golang 中的常见字节操作

简介

在Go语言中, 常用来处理字节操作的数据类型是字节数组[N]byte(或者切片[]byte)

为了更方便的处理字节操作, 我们可以将[]byte重新定义一个类型, 比如 Bytes

type Bytes []byte

字节数组与字符串

Bytes 转 string

b := Bytes{232, 191, 153, 230, 152, 175, 228, 184, 128, 228, 184, 170, 229, 173, 151, 231, 172, 166, 228, 184, 178}
s := string(b)
fmt.Println(s)

string 转 Bytes

s := "这是一个字符串"
b := Bytes(s)
fmt.Println(b)

字节数组与整数、浮点数

int16, uint16, int32, uint32, int64, uint64, float32, float64 转 Bytes

可以使用binary库的Write函数来实现对应的转化

  1. 我们先看binary库的Write函数定义:
func Write(w io.Writer, order ByteOrder, data interface{}) error

表明任何一个实现了 io.Writer协议的结构体对象都可以调用该函数, 但我们的Bytes类型默认好像没有过实现该协议

  1. 我们再看 io.Writer协议:
type Writer interface {
	Write(p []byte) (n int, err error)
}

也就是说, 我们只要给Bytes类型实现一个 Write(p []byte) (n int, err error)函数就可以了:

func (b *Bytes) Write(p []byte) (n int, err error)  {
	*b = append(*b, p...)
	return len(p), nil
}
  1. 当我们对Bytes类型实现io.Writer协议后, 我们再来看转换问题。

我们定义一个通用的转字节数组的函数


func GetBytes(order binary.ByteOrder, data interface{}) Bytes {
	b := Bytes{}
	_ = binary.Write(&b, order, data)
	return b
}
func main() {
	var i16 int16 = 0x1234
	var u16 uint16 = 0x5678
	var i32 int32 = 0x12345678
	var u32 uint32 = 0x87654321
	var i64 int64 = 0x1234567887654321
	var u64 uint64 = 0x8765432112345678
	var f32 float32 = 1234.5678
	var f64 float64 = 12345.67890
	/// 小端模式
	fmt.Println(GetBytes(binary.LittleEndian, i16))
	fmt.Println(GetBytes(binary.LittleEndian, u16))
	fmt.Println(GetBytes(binary.LittleEndian, i32))
	fmt.Println(GetBytes(binary.LittleEndian, u32))
	fmt.Println(GetBytes(binary.LittleEndian, i64))
	fmt.Println(GetBytes(binary.LittleEndian, u64))
	fmt.Println(GetBytes(binary.LittleEndian, f32))
	fmt.Println(GetBytes(binary.LittleEndian, f64))
	
	/// 大端模式
	fmt.Println(GetBytes(binary.BigEndian, i16))
	fmt.Println(GetBytes(binary.BigEndian, u16))
	fmt.Println(GetBytes(binary.BigEndian, i32))
	fmt.Println(GetBytes(binary.BigEndian, u32))
	fmt.Println(GetBytes(binary.BigEndian, i64))
	fmt.Println(GetBytes(binary.BigEndian, u64))
	fmt.Println(GetBytes(binary.BigEndian, f32))
	fmt.Println(GetBytes(binary.BigEndian, f64))
}

这样我们的整数、浮点数都转换成对应的字节数组了

Bytes 转 int16, uint16, int32, uint32, int64, uint64, float32, float64

  • Bytesuint16, uint32, uint64

可以直接使用binary.LittleEndianbinary.BigEndian来转换

func main() {
	bytes := Bytes{1, 2, 3, 4, 5, 6, 7, 8}
	/// 小端模式
	fmt.Println(binary.LittleEndian.Uint16(bytes))
	fmt.Println(binary.LittleEndian.Uint32(bytes))
	fmt.Println(binary.LittleEndian.Uint64(bytes))
	/// 大端模式
	fmt.Println(binary.BigEndian.Uint16(bytes))
	fmt.Println(binary.BigEndian.Uint32(bytes))
	fmt.Println(binary.BigEndian.Uint64(bytes))
}

当然得到uint64后就等于得到了int64, 其他的同理。

  • Bytesfloat32, float64
    再上述得到对应字节序的整数后,可以借助math库的Float32frombitsFloat64frombits
func main() {
	bytes := Bytes{1, 2, 3, 4, 5, 6, 7, 8}
	
	u32le := binary.LittleEndian.Uint32(bytes)
	u32be := binary.BigEndian.Uint32(bytes)	
	u64le := binary.LittleEndian.Uint64(bytes)
	u64be := binary.BigEndian.Uint64(bytes)
	
	/// 小端模式
	fmt.Println(math.Float32frombits(u32le))
	fmt.Println(math.Float64frombits(u64le))
	
	/// 大端模式
	fmt.Println(math.Float32frombits(u32be))
	fmt.Println(math.Float64frombits(u64be))
}

以上为本人新学习到的与字节数组相关的各种转换操作。如果后续有更好的也会更新上来。当然如过读者大人有更好的方式,欢迎评论区讨论学习 *^_^*

你可能感兴趣的:(Go)