ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 关于指针 变量是用来存储数据的,变量的本质是给存储数据的内存地址起了一个好记的别名。 任何程序数据载入内存后,在内存都有他们的地址,这就是指针。而为了保存一个数据在内存中的地址,我们就需要指针变量。 pointer指针是 **引用** 类型。引用类型如果没有初始化的话,默认值是 `nil` golang 语言对应指针操作只有两个: - 取址 `&` - 取值 `*` ## 取址操作 所有数据加载到内存都是有地址的。比如变量也是存在内存中的。`&变量` 即是取址操作,这里演示下如何获取变量地址的。 ```go name1 := "jiaxzeng" fmt.Printf("value: %v, type: %T, pointer: %p\n", name1, name1, &name1) // 运行结果: // value: jiaxzeng, type: string, pointer: 0xc000010260 ``` 现在想使用变量存下这个地址值,所以才有指针变量这一说法。请看下面的指针变量定义 ## 指针变量定义 格式如下三种: 1. var name *type 2. var name *type = &tagName 3. name := &tagName 三种格式定义示例: ```go name2 := "jiaxzeng" // 先定义后赋值 var p1 *string p1 = &name2 fmt.Printf("p1: %v\n", p1) // 定义并初始化 var p2 *string = &name2 fmt.Printf("p2: %v\n", p2) // 简短声明 p3 := &name2 fmt.Printf("p3: %v\n", p3) // 运行结果: // p1: 0xc000010260 // p2: 0xc000010260 // p3: 0xc000010260 ``` 查看变量信息 ```go name3 := "jiaxzeng" fmt.Printf("value: %-12v, type: %-8T, pointer: %p\n", name3, name3, &name3) p4 := &name3 fmt.Printf("value: %-12v, type: %-8T, pointer: %p\n", p4, p4, &p4) // 运行结果: // value: jiaxzeng , type: string , pointer: 0xc000010260 // value: 0xc000010260, type: *string , pointer: 0xc00000e030 ``` 根据运行的结果,画出内存使用的情况 ![](https://img.kancloud.cn/b7/4e/b74e8fb14bc1e91e743c0a115bd231b8_1088x697.png) 有变量存地址值的情况,必然就有根据地址值找值。这一步操作就叫做 **取值** 操作 ## 取值操作 ```go name4 := "jiaxzeng" p5 := &name4 fmt.Println("*p5 is:", *p5) ``` ## new 函数 指针必须在创建内存后才可以使用。如果只声明的话,是没有分配内存空间的。操作取值就会报错。现在有创建个指针类型,又没有想好底层放什么东西,也不想 *变量 报错。golang语言提供个 `new` 函数来初始化指针类型。 new 函数作用: - 用来做内存分配的。 - 内存分配的值 即是 类型的默认值。 - int -> 0 - float32/float64 -> 0 - bool -> false - string -> '' ```go // 只有声明,没有初始化即没有分配内存空间。 // 如果 *name5 会报错。提示 invalid memory address or nil pointer dereference var name5 *string fmt.Printf("name5: %v\n", name5) // 使用new函数分配空间,值即是类型的默认值 var p6 *int = new(int) fmt.Printf("p6: %v, value: %v\n", p6, *p6) // 运行结果: // name5: <nil> // p6: 0xc000018098, value: 0 ``` ## Printf占位符 总结这里出现的占位符 | 占位符 | 描述 | | :-: | :-: | | %p | 打印变量的地址 |