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
```
有疑问加站长微信联系(非本文作者))