目录
指针
一个指针变量指向了一个值的内存地址。类似于变量和常量,在使用指针前需要声明、定义一个指针变量。
声明一个指针变量,格式:
var var_name *type
示例:
var ip *int /* 声明整型指针变量 */
var fp *float32 /* 声明浮点型指针变量 */
指针使用流程:
- 声明指针变量。
- 为指针变量赋值。
- 访问指针变量中指向地址的值。
package main
import "fmt"
func main() {
var a int = 20
var ip *int
ip = &a
fmt.Printf("a 变量的内存地址是: %x\n", &a)
fmt.Printf("ip 变量储存的指针地址是: %x\n", ip)
/* 使用指针访问数据值 */
fmt.Printf("*ip 变量的值: %d\n", *ip)
}
结果:
a 变量的内存地址是: c0000b4008
ip 变量储存的指针地址是: c0000b4008
*ip 变量的值: 20
空指针
当一个指针变量被声明后,却没有分配到任何数值时,它的值为 nil(空)。nil 在概念上和其它语言的 null、None、nil、NULL 一样,都指代零值或空值。
package main
import "fmt"
func main() {
var ptr *int
fmt.Printf("ptr 的值为 : %x\n", ptr)
}
结果:
ptr 的值为 : 0
空指针判断:
if(ptr != nil) /* ptr 不是空指针 */
if(ptr == nil) /* ptr 是空指针 */
双重指针
双重指针,即指向指针的指针。
示例:
var ptr **int;
示例:
package main
import "fmt"
func main() {
var a int = 3000
var ptr *int
var pptr **int
ptr = &a
pptr = &ptr
fmt.Printf("变量 a = %d\n", a)
fmt.Printf("指针变量 *ptr = %d\n", *ptr)
fmt.Printf("指向指针的指针变量 **pptr = %d\n", **pptr)
}
结果:
变量 a = 3000
指针变量 *ptr = 3000
指向指针的指针变量 **pptr = 3000
甚至,还可以写成三重指针,即:指向指针的指针的指针。
ptr3 -> ptr2e -> ptr1 -> a
示例:
package main
import "fmt"
func main() {
var a int = 1
var ptr1 *int = &a
var ptr2 **int = &ptr1
var ptr3 ***int = &ptr2
// 依次类推
fmt.Println("a:", a)
fmt.Println("ptr1", ptr1)
fmt.Println("ptr2", ptr2)
fmt.Println("ptr3", ptr3)
fmt.Println("*ptr1", *ptr1)
fmt.Println("**ptr2", **ptr2)
fmt.Println("***ptr3", ***ptr3)
}
结果:
a: 1
ptr1 0xc00012c008
ptr2 0xc000124018
ptr3 0xc000124020
*ptr1 1
**ptr2 1
***ptr3 1
向函数传递指针参数
传入指针实参,显然是一次引用传递,只需要在函数声明的形参列表上设置为指针类型即可。在函数调用时可以改变其值。
package main
import "fmt"
func main() {
var a int = 100
var b int= 200
swap(&a, &b);
fmt.Printf("交换后 a 的值 : %d\n", a)
fmt.Printf("交换后 b 的值 : %d\n", b)
}
/* 交换函数这样写更加简洁,也是 Golang 的特性 */
func swap(x *int, y *int){
*x, *y = *y, *x
}
结果:
交换后 a 的值 : 200
交换后 b 的值 : 100