在Go语言中, 常用来处理字节操作的数据类型是字节数组[N]byte
(或者切片[]byte
)
为了更方便的处理字节操作, 我们可以将[]byte
重新定义一个类型, 比如 Bytes
type Bytes []byte
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)
s := "这是一个字符串"
b := Bytes(s)
fmt.Println(b)
可以使用binary
库的Write
函数来实现对应的转化
binary
库的Write
函数定义:func Write(w io.Writer, order ByteOrder, data interface{}) error
表明任何一个实现了 io.Writer
协议的结构体对象都可以调用该函数, 但我们的Bytes
类型默认好像没有过实现该协议
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
}
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
转 uint16
, uint32
, uint64
可以直接使用binary.LittleEndian
和binary.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
, 其他的同理。
Bytes
转 float32
, float64
math
库的Float32frombits
和Float64frombits
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))
}