一、指针相关字段解释
二、变量声明存储结构
图中变量的声明假设是在函数内进行的,均属于局部变量。
图表解释,通常来说变量名i、aj并不会真的独立出现在栈上的某个位置,都是伴随着一些操作出现的,加减法,赋值等操作。
例如汇编加法指令,ADD $i,3,为变量i加3,通过变量名i这个地址找到真正的值,然后加3。
关于变量值分配到堆上或者栈上,是和编译器编译时分析有关,正常可以理解为,被多个函数使用到的变量内容,需要分配到堆上,其余分配到栈上。
上图中,可以看到指针变量aj存储的是一个内存地址,该地址指向变量值2。
扩展一下:
var aj2 = aj,aj2这个变量是怎么存储的呢?首先aj和aj2的变量值内容肯定是完全一致的,但是aj和aj2这两个变量名会指向同一个变量值吗?
从这里我们大概就明白了,复制时,指针类型和别的类型一样,都会把自己的变量值复制一份传递给新的变量,但是指针变量特殊的一点是,他的值内容存储的是指针,复制过去的也是指针内容,从而这两个指针变量的值都指向了同一块内存。
三、指针操作示例代码
示例一:函数内更改指针变量的地址内容
type TestStruct struct {
V1 string
}
func main() {
ts := &TestStruct{
V1: "初始化测试!",
}
fmt.Println(ts)
ts2 := ts
ts2.V1 = "初始化测试2!"
fmt.Println(ts)
ts2 = &TestStruct{
V1: "重新初始化测试结构体",
}
fmt.Println(ts)
}
这一段代码输出内容如下:
解释:
ts2:=ts复制时,这两个结构体指针保存的内存地址是一样的,都是指向“初始化测试”这个结构体值内容。
ts2=&TestStruct{V1: "重新初始化测试结构体"},给ts2指针变量重新赋值时,ts2保存的内存地址发生了更换,并且指向了 "重新初始化测试结构体"这个值内容。然而ts的变量值内容并没有发生改变,所以打印内容还是“初始化测试2!”。
示例二:更改接收者指针变量的地址内容
func main() {
ts1 := &TestStruct{
V1: "初始化测试",
}
fmt.Println(ts1)
ts1.ReSet("重新初始化测试结构体")
fmt.Println(ts1)
}
type TestStruct struct {
V1 string
}
// ReSet 重设接收者变量指向内容
func (ts *TestStruct) ReSet(value string) {
ts = &TestStruct{
V1: value,
}
}
这一段代码内容输出如下:
解释:
调用Reset方法时,为接收者ts指针变量重新初始化了一次,相当于将接收者指针存储的内容做了一次替换,使之指向了“重新初始化测试结构体”这个值内容,但是main函数ts1指针变量的指针内容并没有发生变化。变量存储变化图如下:
特别指出一点,Reset和main函数各有各的栈空间,为了方便描述就将他们的变量放在一块了。