通过例子深入理解指针

guoapeng · 2019-10-11 20:32:40 · 815 次点击 · 预计阅读时间 4 分钟 · 大约8小时之前 开始浏览    
这是一个创建于 2019-10-11 20:32:40 的文章,其中的信息可能已经有所发展或是发生改变。

golang 每执行一次取地址操作,就会产生一个指针对象,这些对象可以层层包裹,这一点和c, c++ 以及java 的 reference 还是有很大的差别的

package main

import (
    "fmt"
    "reflect"
)

type Student struct {
    name string
    age  int ``
}

func (s *Student) Study() {
    fmt.Print("Studying go point...\n")
}

func (s Student) Learn() {
    fmt.Print("Learning go point...\n")
}

func main() {
    stu3 := Student{name: "eagle", age: 10}
    (&stu3).Learn() // 注意 (&stu3).Learn() 和 &stu3.Learn()的区别
    fmt.Printf("               stu3'saddress:%p, type: %T, value: %v\n  ", &stu3, stu3, stu3)
    stu3Addr := &stu3 // 这里 stu3Addr 是一个新的指针对象 *Student
    fmt.Printf("         stu3Addr'saddress:%p, type: %T, value: %v\n", &stu3Addr, stu3Addr, stu3Addr)
    stu3AddrAddr := &stu3Addr
    fmt.Printf("       stu3AddrAddr'saddress:%p, type: %T, value: %v\n", &stu3AddrAddr, stu3AddrAddr, stu3AddrAddr)
    stu3AddrAddrAddr := &stu3AddrAddr
    fmt.Printf("   stu3AddrAddrAddr'saddress:%p, type: %T, value: %v\n", &stu3AddrAddrAddr, stu3AddrAddrAddr, stu3AddrAddrAddr)

    fmt.Printf(" **stu3AddrAddrAddr'saddress:%p, type: %T, value: %v\n", &*stu3AddrAddrAddr, *stu3AddrAddrAddr, *stu3AddrAddrAddr)
    fmt.Printf(" **stu3AddrAddrAddr'saddress:%p, type: %T, value: %v\n", &**stu3AddrAddrAddr, **stu3AddrAddrAddr, **stu3AddrAddrAddr)
    fmt.Printf("***stu3AddrAddrAddr'saddress:%p, type: %T, value: %v\n", &***stu3AddrAddrAddr, ***stu3AddrAddrAddr, ***stu3AddrAddrAddr)
    xx := &**stu3AddrAddr // 这里的 xx 打印出来的地址和上一行会一样吗? 为什么?
    fmt.Printf("                xx's address:%p, type: %T, value: %v\n", &xx, xx, xx)
    xxx := &xx                           // 那么如果把以上两个赋值语句合成一句xxx := &&***stu3AddrAddrAddr 会怎样呢,为什么?
    fmt.Printf("               xxx's address:%p, type: %T, value: %v\n", &xxx, xxx, xxx)
    Inspect(xxx)
    Inspect(stu3AddrAddrAddr)
    //stu3.Learn()
    //(**stu3AddrAddrAddr).Learn()
}

func Inspect(obj interface{}) {
    t := reflect.TypeOf(obj)
    v := reflect.ValueOf(obj)
    fmt.Printf("====================%v======================\n", t)
    fmt.Printf("type is %v, value is %v\n", t, v)
    //fmt.Printf("kind is %v\n", t.Kind())  //both methods are ok to get kind
    fmt.Printf("kind is %v\n", v.Type().Kind())
    fmt.Printf("the name of the type is %v\n", t.Name())
    fmt.Printf("the full name of the type is %v\n", t.String())
    fmt.Printf("the size of the type is %v\n", t.Size())
    switch t.Kind() {
    case reflect.Ptr:
        fmt.Println("pointing to type :", t.Elem())
        fmt.Printf("pointing to address :%v\n", v.Elem()) // 注意 t.Elem() 和v.Elem的差别
    default:
        fmt.Printf("the mum of method is  %v \n", v.Pointer())
    }
}

输出

Learning go point...
               stu3'saddress:0xc000004480, type: main.Student, value: {eagle 10}
           stu3Addr'saddress:0xc000006030, type: *main.Student, value: &{eagle 10}
       stu3AddrAddr'saddress:0xc000006038, type: **main.Student, value: 0xc000006030
   stu3AddrAddrAddr'saddress:0xc000006040, type: ***main.Student, value: 0xc000006038
 **stu3AddrAddrAddr'saddress:0xc000006038, type: **main.Student, value: 0xc000006030
 **stu3AddrAddrAddr'saddress:0xc000006030, type: *main.Student, value: &{eagle 10}
***stu3AddrAddrAddr'saddress:0xc000004480, type: main.Student, value: {eagle 10}
                xx's address:0xc000006048, type: *main.Student, value: &{eagle 10}
               xxx's address:0xc000006050, type: **main.Student, value: 0xc000006048
====================**main.Student======================
type is **main.Student, value is 0xc000006048
kind is ptr
the name of the type is 
the full name of the type is **main.Student
the size of the type is 8
pointing to type : *main.Student
pointing to address :&{eagle 10}
====================***main.Student======================
type is ***main.Student, value is 0xc000006038
kind is ptr
the name of the type is 
the full name of the type is ***main.Student
the size of the type is 8
pointing to type : **main.Student
pointing to address :0xc000006030

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

815 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传