通过例子深入理解指针

guoapeng · · 657 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

golang 每执行一次取地址操作,就会产生一个指针对象,这些对象可以层层包裹,这一点和c, c++ 以及java 的 reference 还是有很大的差别的 ```go 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()) } } ``` 输出 ```shell 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

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