go内存地址

go内存地址

  • 内存地址
    在go中获得该变量的内存地址 用&a
func main() {
    a := 43
    b := &a
    fmt.Println("a - ", a)
    fmt.Println("b - ", b)
}

首先声明了一个int类型的变量a,它的值为0,然后又声明了一个a的引用b,b只是a的一个别名而已,并没有占用内存空间。实际上他们是同一个同西,在内存中占用同样的一个存储单元。

  • 变量名是个什么东西 赋的值又是个什么东西
    char a;
    1 变量
    用来标识(identify)一块内存区域,这块区域的值一般是可以更改的,这就是它“变”的由来,但是我们可以通过使用如
    const等一些修饰符号来限定这一内存区域的操作特性(characteristic),即变量的操作特性。用const修饰的使变量不能更改
    的就和常量一样的变量叫做常变量。
    2 变量名
    是一个标识符(identifier),用来指代一块内存区域,即变量,使用变量使我们操作内存以区域(area),以块(block)为单位,
    提高了方便性。
    3 变量名不会出现在机器中
    你的机器代码中,是不会出现变量名的;变量名是给我们程序员操作内存来使用的。
    想想在汇编年代,没有变量名,我们操作内存,都是用地址来直接操作的,还要控制区域大小;当然汇编语言已经有了简·
    单的变量。
    4 赋值操作过程
    对于编译器,它会搜集我们的变量名,比如我们定义了一个全局的int a;那么编译器都为我们做了什么呢?
    它会为程序预留4个字节的空间(假设在32位平台),并把我们的变量名“a”保存进符号表,并用这个符号表的索引对应实
    际的空间
    如果下面出现b = a;那么它就会根据符号表找到变量的真正的物理位置,取得它的值,赋给b。
    这是写编译器需要做的,我们需要建立符号表。
    但是实际在汇编层次上,操作的都是地址而已,不存在任何名称了。
    1、a 表示一块内存空间 表示本身的值
    2、&a 表示当前内存空间的地址 值所对应的地址
    那么指针变量就具有3种形态:
    1、a 表示指针a对应的内存空间(可以说就是指针本身的值)
    2、&a 表示当前指针对应的内存空间的首地址(存放指针的地址) 指针就是一个地址
    3、*a 表示指针a所指向的变量对应的整个内存空间。(指针指向的空间)

  • 指针变量 普通变量 内存 和地址的全面对比
    1 内存
    是什么,内存是实实在在的硬件,可以存数据,运行时的数据全放在里面
    想想一点,内存就像一个个的小个子,每个格子的带下是一个一个字节,可以存放一个字节的数据
    2 地址
    地址是内训的一个表标识,每一个地址度对应一个内训,所以内存和地址一一对相应
    3 普通变量
    如 char a; 就是一个普通变量。普通变量a其实是语言本身创造了,是为了更方便的表示内存。我们对a进行访问其实就
    是直接对内存进行访问。至于a表示的内存的地址是多少,程序员一般不用关心。编译器会自动分配地址,也就是常说的
    为a分配一个地址。如果想知道a的地址也可以通过&a得知。
    4 指针变量
    他和普通变量的区别在于,普通变量是和一块内存空间关联。而指针变量却是和两块内存空间想关联:

5 go中所有的都是按值传递,对于复杂类型,传的是指针的拷贝

     func main() {
    var m map[int]string = map[int]string{
        0: "0",
        1: "1",
    }
    mm := m
    fmt.Printf("%p\n", &m)  //0xc42002a028
    fmt.Printf("%p\n", &mm) //0xc42002a030
    fmt.Println(m)          // map[0:0 1:1]
    fmt.Println(mm)         //map[1:1 0:0]
    changeMap(m)
    fmt.Printf("%p\n", &m)  //0xc42002a028
    fmt.Printf("%p\n", &mm) //0xc42002a030
    fmt.Println(m)          //map[2:2 0:0 1:1]
    fmt.Println(mm)         //map[0:0 1:1 2:2]
    }
    func changeMap(mmm map[int]string) {
    mmm[2] = "2"
    fmt.Printf("changeMap func %p\n", mmm) //changeMap func 0xc420014150
   }

直接传指针 也是传指针的拷贝

func main() {
    var m map[int]string = map[int]string{
        0: "0",
        1: "1",
    }
    mm := m
    fmt.Printf("%p\n", &m)  //0xc42002a028
    fmt.Printf("%p\n", &mm) //0xc42002a030
    fmt.Println(m)          // map[0:0 1:1]
    fmt.Println(mm)         //map[1:1 0:0]
    changeMap(&mm)
    fmt.Printf("%p\n", &m)  //0xc42002a028
    fmt.Printf("%p\n", &mm) //0xc42002a030
    fmt.Println(m)          //map[2:2 0:0 1:1]
    fmt.Println(mm)         //map[0:0 1:1 2:2]
}
func changeMap(mmm *map[int]string) {
    mmm = nil
    fmt.Printf("changeMap func %p\n", mmm) //changeMap func 0xc420014150
}
    原文作者:seven_son
    原文地址: https://www.jianshu.com/p/c4dd003b48d7
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞