-
package main import ( "fmt" ) func swap(a, b int) { var tmp int tmp = a a = b b = tmp } func ptrSwap(a, b *int) { var tmp int tmp = *a *a = *b *b = tmp } /** * 指针是变量,只是变量存储的值是另一个变量的地址 */ func main() { { var a int = 10 fmt.Printf("address of a variable: %x\n", &a) var ip *int //未初始化的指针变量存储的值为nil fmt.Printf("address of ip variable: %x\n", ip) fmt.Printf("address of ip variable: %x\n", &ip) ip = &a //这里可以看指针变量ip存储的值是变量a的地址, 我们可以通过*ip来取变量ip实际指向的值(不是存储的值) fmt.Printf("address of ip variable: %x\n", ip) fmt.Printf("value of ip variable: %d\n", *ip) } /** * 指针数组,数组我们在array.go中已经介绍过了 * 我们来说一下指针数组: 指针数组就是存储指针的数组 * []int 数组我们来存储int型数据 * []*int */ { ptra := []int{10, 56, 32} var ptr [3]*int for i := 0; i < 3; i++ { ptr[i] = &ptra[i] //这里我们可以看到指针数组数组元素存储的是ptra对应元素的地址 } for i := 0; i < 3; i++ { fmt.Printf("value of a[%d] = %d\n", i, *ptr[i]) } } /** * 指针的指针 var pptr **int * * 如果理解了指针那么指针的指针就不难理解。指针的指针就是在原有指针的基础上发现*pptr指向不是一个变量值而还是一个地址,这样要取pptr存储的值就需要 * *(*pptr) 这样更容易理解 * */ { var a int = 10 var ptr *int var pptr **int ptr = &a //指针变量ptr存储的是变量a的地址 pptr = &ptr //指针的指针变量pptr存储的是变量ptr的地址 //pptr(ptr地址)--->ptr(a地址)也就是 pptr(ptr(&a)) x()可以理解为x存储的值 fmt.Printf("value of **pptr = %d, *pptr = %x, *ptr = %d, ptr = %x, &a = %x\n", **pptr, *pptr, *ptr, ptr, &a) } /** * 指针作为函数参数 * 要理解指针作为函数参数为什么可以改变参数值,首先要明白堆和栈的区别 * * 我们都知道全局变量一般在堆中申请地址、函数内部变量一般在栈中申请,栈中的变量随着代码段{}的结束就会释放掉(如上面的代码段{}、重复的变量可以申请的原因) * 那么当我们把参数传递给函数时,那么在函数内也就是栈的操作、当函数退出后所有的变量就会释放掉,这也就是为什么(swap(a, b int)不能交换a, b值得原因) * */ { var a, b int = 12, 24 swap(a, b) fmt.Printf("a = %d, b = %d\n", a, b) ptrSwap(&a, &b) //这里我们传递的是地址,当然你在函数里面直接对变量a或b操作退出函数之后也会释放掉,没有作用。 //我们绕过直接操作指针变量,而是操作指针变量指向的值,那么在函数退出后就算释放指针变量a、b也没关系,因为我们根本没有对变量a、b进行操作 fmt.Printf("a = %d, b = %d\n", a, b) } }