> go语言github项目:https://github.com/minibear2333/how_to_code
`go` 语言的教程拖拖拉拉写了好久了,本身比较简单,按部就班的写影响到了我的学习进度,所以我要加速度了,从这一篇开始。话不多说现在开始。
[TOC]
### 指针
`c` 中有指针的概念,在 `go` 中也有,但是实际上用的比较少,因为指针容易出错,而且不易阅读。
每个变量都有他的地址
```Go
var a int
fmt.Printf("a 的地址是:%p \n", &a)
```
输出
```
a 的地址是:0xc0000b2008
```
指针用来存地址
```Go
//声明 变量名 + 指针类型 , 命令规则以ptr结尾
var ptr *int /* 指向整型*/
// var fp *float32 /* 指向浮点型 */
ptr = &a // 变量内部存的值是普通类型,指针内部存的值是地址
fmt.Printf("ptr 存的值是:%p \n", ptr)
```
输出,可以看到 `ptr` 存的值就是 `a` 的地址。
```
ptr 存的值是:0xc0000b2008
```
存的就是 a 的地址,ptr 的指向\*ptr 肯定就是 a 本身了。
```Go
if a == *ptr {
fmt.Println("a == *ptr")
}
```
输出
```
a == *ptr
```
### 指针的作用
指针可以消灭掉返回值,直接对参数做改变。
定义一个交换函数,形参为指针类型
```Go
func swap(x *int, y *int) {
var temp int
temp = *x /* 保存 x 地址的值 */
*x = *y /* 将 y 赋值给 x */
*y = temp /* 将 temp 赋值给 y */
}
```
调用
```Go
a := 100
b := 200
//操作地址,不需要返回
swap(&a, &b)
fmt.Printf("交换后 a 的值 : %d\n", a)
fmt.Printf("交换后 b 的值 : %d\n", b)
```
输出
```
交换后 a 的值 : 200
交换后 b 的值 : 100
```
虽然可以这么做,但是不推荐,因为 `go` 比 `c++` 多出来多返回值的特性,所以这里写在返回里可读性更强。
PS1: 但如果你的参数是比较复杂的类型,比如数组。用指针可以节省空间。
PS2: 对引用类型的操作会改变原引用类型的值,这里与指针有异曲同工之妙。
### 多维指针
刚刚用到的指针,只不过指向一个变量的地址,他就被叫做一维指针。
```Go
var ptr *int
ptr = &a
```
指针本身也是一个变量,是变量就有地址,所以指针也可以被取地址。
```Go
var ptr *int
pptr = &ptr
```
`*int` 类型的指针存的是 `int` 类型数据的地址,得到 `*变量类型` 就是他的指针,推导出指向 `*int` 变量的指针为 `**int` 类型,这种类型被称为二维指针,每多一个 `*` 就多一个维。
```Go
var a int
var ptr *int //一维
var pptr **int // 二维
var ppptr ***int // 三维
ptr = &a
pptr = &ptr
ppptr = &pptr
fmt.Printf("a的地址:%p \n", &a)
fmt.Printf("ptr存的地址:%p \n", ptr)
fmt.Printf("pptr存的地址的指向:%p \n", *pptr)
fmt.Printf("ppptr存的地址的指向的指向:%p \n", **ppptr)
```
输出
```
a的地址:0xc000014090
ptr存的地址:0xc000014090
pptr存的地址的指向:0xc000014090
ppptr存的地址的指向的指向:0xc000014090
```
PS1: 日常工作中,不建议使用多维指针,可读性不好,容易犯错误,一层指针能搞定的,一定不要使用多维炫技术。不然过几个月你自己都看不懂。
PS2: 不得不使用二维指针的场景:你希望在一个函数的参数中改变一个指针的值,你就只能传这个指针的指针给这个函数。
PS3:多维指针的唯一好处:减少传参
**你在工作中啥时候用到了指针/多维指针?**
- 安装与下载
- 投稿大纲
- 第一章、跑起来
- 为什么要学 go 语言?
- 让你的 Golang 项目在 IDE 里跑起来
- 第一个 go 程序
- go mod最佳实践
- 第二章、语言基础
- 声明【变量】的各种方式
- 常量+各种类型转换
- switch和type switch
- 循环语句的多种形式、死循环、break/continue
- range深度解析
- 第三章、函数和容器
- 函数简单使用和基本知识解析
- 匿名函数和闭包
- 可变参数
- 集合(map)
- 数组和切片
- 切片知识补充
- 第四章、指针、结构体、接口和异常处理
- 指针讨论
- 结构体
- 接口与多态
- 异常处理
- 第五章、再学一点运用自如
- 其他常用操作
- Go文件操作大全
- Go代码基本标准规范
- 切片排序sort包的使用
- Golang打镜像Dockerfile的写法
- 等待goroutine完成任务,循环中使用goroutine
- kinping.flag包读取命令行配置