go 变量和类型

Created

2024-10-28 13:26:46

Updated

2024-10-28 13:27:07

一个变量就是一块内存(有的变量不占内存空间),
变量的类型规定了你 如何从这块内存里读取数据和写入数据,且给这个类型的变量一些”操作方法”,比如 数组的下标操作

1 大小端

Diagram

2 代码判断大小端

var val int32 = 1
ptr := unsafe.Pointer(&val)
IsLittleEndian := *(*byte)(ptr) == 1
println(IsLittleEndian) //true 就是小端模式 

3 变量类型与类型转换

变量的类型规定了你如何从这块内存里读取数据和写入数据
类型的转换无非就是你换了一种读写数据的方式而已

func main() {
    // 1000 0011
    var a uint8 = 131
    println(a)
    // 变成有符号的, 那么它的数据的读取方式就变了
    // 1000 0011 负数的补码
    // 反码 1000 0010
    // 原码 1111 1101 = -125
    b := int8(a)
    println(b) // -125
}

3.1 一块可读写的内存,是不是可以按照我任意的方式来读写呢?

是的, 你想怎么读写,就怎么读写

package main

import (
    "unsafe"
)

type FF struct {
    i int32
    j int8
    k int8
}

func main() {
    // 我们这里假定 z和 a 变量之间是连续的 (因为可能不一定是连续的!)
    var z int32 = 1800
    var a, b, c, d int8 = 2, 4, 3, 1

    ptr := unsafe.Pointer(&d)
    // 格式化(类型转换)  理解为 你想这么去读写这块内存上的数据
    // 这里当然你可以就用 (*int32)(ptr) 来格式化 读取4个字节的测试
    ff := (*FF)(ptr)
    //0xc00004c753 0xc00004c752 0xc00004c751 0xc00004c750
    println(&a, &b, &c, &d)
    // 0xc00004c754
    println(&z)
    // 0xc00004c750 0xc00004c754
    println(&ff.i, &ff.j)
    // 33817345 8 7
    println(ff.i, ff.j, ff.k)
    // 直接修改了z 原来那块内存上某个字节上的数据了.
    // 当然如果要去改变量的某个字节上的数据, 可以用位运算..
    ff.j = 9
    // 1801
    println(z)
    ff.k = 1
    // 265
    println(z)

}
Diagram
  • 再举个例子
package main

import (
    "unsafe"
)

type dd struct {
    i1  int8
    arr [3]int8
}

func main() {
    d := 33817345
    // 想怎么格式化就怎么格式化
    // 想怎么读写数据就怎么格式化它
    d2 := (*dd)(unsafe.Pointer(&d))
    println(d2.i1, d2.arr[0], d2.arr[1], d2.arr[2])
    d2.arr[0] = 6
    println(d)
}

理解了类型,使用起 (unsafe.Pointer) 会变得更容易

4 指针的类型

Tip
  • 指针: 它的值是一个地址, 一般说它指向一个内存地址
  • 指针类型: 说明了你用什么样的方式结构去读取它指向的那块内存
// 新的结构= 新的内存读取方式
newPtr:=(*新的结构)(unsafe.Pointer(地址))
Back to top