前文概览

前面文章介绍了 Go 语言原生数据类型。Golang 中具备丰富的数据类型,基本类型有整型、浮点数、布尔型、字符串型等,除此之外,还有切片、结构体、指针、通道、map、数组等其他类型。本文将会介绍 GO 语言中的指针基本概念与相关用法。

指针

Golang 限制了指针类型的偏移和运算能力,使得指针类型具备了指针高效访问的特性,但又不会发生指针偏移,避免了非法修改敏感数据的问题。同时 Golang 中提供的自动垃圾回收机制,也减少了对指针占用内存回收的复杂性。

指针只要包含三个概念:

  • 指针地址

  • 指针类型

  • 指针取值

在程序运行的过程中,每一个变量的值都保存在内存中,变量对应的内存有其特定的地址。假设某一个变量的类型为 T,在 Golang 中,我们可以通过 & 取址符号获取该变量对应内存的地址,生成该变量对应的指针。此时,变量的内存地址即生成的指针的值,指针类型即 *T,称为 T 的指针类型,* 代表指针。

我们可以运行一下 Pointer.go,查看它的执行结果。

package mainimport "fmt"func main()  {//声明一个 string 类型str := "Golang is Good!"//获取 str 的指针strPrt := &strfmt.Printf("str type is %T, and value is %v\n", str, str)fmt.Printf("strPtr type is %T, and value is %v\n", strPrt, strPrt)
}

执行结果如下:

str type is string, and value is Golang is Good!
strPtr type is *string, and value is 0xc0000621c0

可以看到 str 的类型为 string,它的指针 strPtr 的类型为 *string,指针的值为 0xc0000621c0,即变量 str 内存中的地址。

当然我们可以继续对指针 strPtr 进行取址操作,如下所示:

strPtrPtr := &strPrt
fmt.Printf("strPtrPtr type is %T, and value is %v\n", strPtrPtr, strPtrPtr)

它的输出结果为:

strPtrPtr type is **string, and value is 0xc00007a018

我们此时获取了 strPtr 对应内存的地址,并保存到 strPtrPtr 指针中。

除了提供对变量进行取址操作获取变量指针的 & 操作,Golang 中也提供了根据指针获取变量值的取值操作 *,通过 * 可以获取指针对应变量的值和对变量进行赋值操作,具体代码如下所示:

package mainimport "fmt"func main()  {str := "Golang is Good!"strPrt := &strfmt.Printf("str type is %T, value is %v, address is %p\n", str, str, &str)fmt.Printf("strPtr type is %T, and value is %v\n", strPrt, strPrt)newStr := *strPrt //获取指针对应变量的值fmt.Printf("newStr type is %T, value is %v, and address is %p\n", newStr, newStr, &newStr)*strPrt = "Java is Good too!" //通过指针对变量进行赋值fmt.Printf("newStr type is %T, value is %v, and address is %p\n", newStr, newStr, &newStr)fmt.Printf("str type is %T, value is %v, address is %p\n", str, str, &str)}

输出的结果为:

str type is string, value is Golang is Good!, address is 0xc0000621c0
strPtr type is *string, and value is 0xc0000621c0
newStr type is string, value is Golang is Good!, and address is 0xc0000621f0
newStr type is string, value is Golang is Good!, and address is 0xc0000621f0
str type is string, value is Java is Good too!, address is 0xc0000621c0

在上述代码中,我们通过 strPtr 指针获取 str 的值赋予给 newStr 变量。可以观察到 strnewStr 是两个不同的变量,它们对应的内存地址不一样,赋值过程中发生了值拷贝。通过指针修改 str 变量的值并不会影响到 newStr,因为这两个变量对应的内存地址不一样。

除了使用 & 对变量进行取址操作创建指针,还可以使用 new 函数直接分配内存,并返回指向内存的指针,此时内存中的值会被初始化为类型的默认值。如下例子所示:

str := new(string)
*str = "Golang is Good!"

在上述代码中,通过 new 函数创建了一个 *string 指针,并通过指针对其进行赋值。

在 Golang 的 flag 包中,命令行参数一般以指针的返回,下面我们演示一个读取命令行参数的例子,如下代码所示:

package mainimport ("flag""fmt"
)func main()  {//定义一个类型为 string,名称为 surname 的命令行参数//参数依次是命令行参数的名称,默认值,提示surname := flag.String("surname", "王", "您的姓")//定义一个类型为 string,名称为 personalName 的命令行参数//除了返回指针类型结果,还可以直接传入变量地址获取参数值var personalName stringflag.StringVar(&personalName, "personalName", "小二", "您的名")//定义一个类型为 int,名称为 id 的命令行参数id := flag.Int("id", 0, "您的 ID")//解析命令行参数flag.Parse()fmt.Printf("I am %v %v, and my id is %v\n", *surname, personalName, *id)}

在上述代码中可以看到,除了直接获取指针类型的返回结果,还可以将参数变量的指针传递给 flag.*Val 方法,获取命令行参数的值。输入以下的执行参数:

go run Flag.go -surname="苍" -personalName="小屋" -id=100

Golang 中 flag 支持多种样式的命令行参数,包括:

-id=100
--id=100
-id 100
--id 100

输出结果如下:

I am 苍 小屋, and my id is 100

小结

在 C/C++ 语言中,指针直接操作内存的特性使得 C/C++ 具备极高的性能,它可以使开发人员操作大块内存数据。与此同时,指针偏移、运算和内存释放可能引发的错误也让指针编程饱受诟病。本文主要介绍了 Go 语言中指针的基本概念与使用。Go 语言限制了指针类型的偏移和运算能力,使得指针类型具备了指针高效访问的特性,但又不会发生指针偏移,避免了非法修改敏感数据的问题。

下面文章将会介绍 GO 中的常量使用。相对于变量运行时可变的特点,常量的值在声明之后是不允许变化。通过const关键字可以声明常量,声明常量的样式与声明变量非常相似。

相关阅读

Go 语言入门系列:原生数据类型

Go 语言入门系列:基本语法介绍之变量的声明与初始化

Go 语言入门系列:第一个 Go 程序

Go 语言入门系列:Go 语言:环境安装

Go 语言入门系列:指针的基本应用相关推荐

  1. C语言入门系列 -运算符

    C语言入门系列 - 运算符 第一节 C 语言基础以及基本数据类型 第二节 C 语言运算符 第三节 C 语言控制语句 第四节 C 语言自定义函数 第五节 C 语言修饰变量的关键字 第六节 C 语言构造数 ...

  2. C语言入门系列 - 自定义函数

    C语言入门系列 - 自定义函数 第一节 C 语言基础以及基本数据类型 第二节 C 语言运算符 第三节 C 语言控制语句 第四节 C 语言自定义函数 第五节 C 语言修饰变量的关键字 第六节 C 语言构 ...

  3. C语言入门系列一之C语言介绍、环境配置和运行执行

    鉴于书本和教材文字过多.又难懂的缺点,所以我打算写一系列通俗移动的C语言入门教程,让大家在短时间内学习和掌握C语言,以及遇到C语言的一些问题该如何得到快速的解决.希望这些系列的教程,能够帮助到大家!该 ...

  4. C语言入门之指针用法教程

    C语言入门之指针用法教程 这篇文章主要介绍了C语言入门之指针用法教程,主要对C语言中指针的本质及常见用法做了较为通俗易懂的分析,是后续深入学习C语言的基础,需要的朋友可以参考下 undefined u ...

  5. Go 语言入门系列:基本语法介绍之变量的声明与初始化

    各位同学端午安康! 前文回顾 前面的文章介绍了 Go 相关的特性与入门案例,对于一门编程语言,变量和语法是我们首先需要掌握的.Go 在语法上与 C 语言有很多相似支持,但是比 C 语言更加简约.如果你 ...

  6. C语言入门系列之6.一维和二维数组

    数组 一.数组的概念 二.一维数组的定义与引用 1.一维数组定义 注意事项 常见错误 扩展:一维数组在内存中的存放 2.一维数组的引用 注意事项 3.一维数组的初始化 初始化赋值 动态赋值 三.二维数 ...

  7. C语言入门系列之10.结构体和共用体

    文章目录 一.结构体变量的基本使用 1.概述 2.定义结构体类型变量的方法 3.结构体变量的引用 4.结构体变量的初始化 二.结构体的高级应用 1.结构体数组 Ⅰ定义结构体数组 Ⅱ结构体数组的初始化 ...

  8. R语言入门系列-软件下载,环境搭建,数据导入导出

    1. 为什么是R? 现在数据科学,深度学习领域最受欢迎的是Python, 那么为什么要学习R语言,Python 和 R 的优势分别在哪儿? 简单来说,R语言更适用与研究,偏数理统计,小而精,适合将来做 ...

  9. r语言dmy()函数转化出现na_R语言入门系列之二

    2数据管理与可视化 2.1数据预处理 在进行正式的数据分析之前,通常要对数据进行处理.而读取数据仅仅是最简单的,之后还要进行数据的筛选.排序.转换等.数据框是最方便的数据存储.管理对象.R有很多内置的 ...

  10. R语言实战应用精讲50篇(三十一)-R语言入门系列-tidyverse数据分析流程

    1. 数据分析的开端,Tidyverse? tidyverse 是一个清晰的 R 包集合,在数据操作.探索和可视化领域提供统一的数据科学解决方案,这些解决方案具有共同的设计理念.它是由 RStudio ...

最新文章

  1. 手工构建ISO的基本步骤
  2. 云上人第七代产品简单的代码
  3. 关于sqlserver中xml数据的操作
  4. 40-400-030-运维-优化-MySQL入门调优脚本tuning-primer的使用
  5. python全栈开发工程师_老男孩Python高级全栈开发工程师三期完整无加密带课件(共104天)...
  6. c语言中eof的作用,C语言中EOF是什么意思?
  7. 计算机显卡驱动全部卸载,Win7彻底卸载NVIDIA显卡驱动程序的办法
  8. 鸿雁召开智能家居新品发布会,智能面板等多款全屋智能新品亮相
  9. 数据库查询语句优化,mysql优化,join语句优化附带YYC松鼠短视频系统详细demo效果
  10. android 动画无缝滚动,CSS3动画之无缝滚动
  11. 【OCR】中文街景数据集、场景文本定位识别新网络:End2End-PSL
  12. 从B站、爱奇艺、映客的IPO上市,看国内视频公司的内容审核现状
  13. docker gpu 创建 训练环境_通过Dockerfile创建caffe-gpu环境
  14. MPLAB IDE V8.8进行程序烧写
  15. 计量经济学计算机实验,《计量经济学》上机实验答案.doc
  16. 移动端h5唤起键盘_移动端H5监听键盘弹出和收起
  17. Verilator简介与使用
  18. 全面撤出印度市场,郭台铭终于明白了到底谁成就了富士康
  19. 什么前浪后浪,我们只不过是时代大潮中的一朵小浪花
  20. 中标麒麟使用centos源_Linux各系统配置yum,apt源

热门文章

  1. pytorch GPU内存管理
  2. 个体营业执照与公司营业执照的区别
  3. OSChina 周三乱弹 ——你是有多寂寞啊,看光头强都……
  4. db2配置、db和dbm
  5. 全球及中国触屏控制器芯片行业研究及十四五规划分析报告
  6. 算力网络走向智能社会,云计算初心未改(一)
  7. 2015 年 Git@OSC 最热门开源项目 Top 50
  8. 32位系统支持多大内存 Windows32位/64位系统最大支持内存详解
  9. 让WindowsXP SP3支持64G内存
  10. FeedSky更新出现很大延时