1. 复合数据类型

Go 语言基本的复合数据类型有指针、数组、切片、字典、通道、结构和接口等。格式如下:

* pointerType    //  指针类型,
[n]elementType  //  数组类型,
[]elementType   //  切片类型,
map [keyType]valueType  //  字典类型
chan valueType  //  通道类型//  结构体类型
struct {fieldType fieldTypefieldType fieldType...
}// 接口类型
interface {method1(inputParams) (returnParams)method2(inputParams) (returnParams)...
}

2. 指针定义

每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go 语言中使用在变量名前面添加&操作符(前缀)来获取变量的内存地址(取地址操作),格式如下:

ptr := &v    // v 的类型为 T

其中 v 代表被取地址的变量,变量 v 的地址使用变量 ptr 进行接收, ptr 的类型为*T,称做 T 的指针类型,*代表指针。

Go 语言的取地址符是 &放到一个变量前使用就会返回相应变量的内存地址。
获取变量在内存中地址:

package mainimport "fmt"func main() {var a int = 10fmt.Printf("变量的地址: %x\n", &a) // 变量的地址: c000018068fmt.Printf("%p", &a)          // %p 打印变量内存地址,指针的值是带有0x十六进制前缀的一组数据。
}

一个指针变量指向了一个值的内存地址。在使用指针前你需要声明指针。指针声明格式如下:

var varName *varType

varType 为指针类型, varName 为指针变量名, * 号用于指定变量是作为一个指针。以下是有效的指针声明:

var ip *int        /* 指向整型*/
var fp *float32    /* 指向浮点型 */

Go 同样支持多级指针,类似 **ip

一个指针变量可以指向任何一个值的内存地址,它所指向的值的内存地址在 32 和 64 位机器上分别占用 4 或 8 个字节,占用字节的大小与所指向的值的大小无关。

当一个指针被定义后没有分配到任何变量时,它的默认值为 nil 。指针变量通常缩写为 ptr

变量、指针和地址三者的关系是,每个变量都拥有地址,指针的值就是地址。

3. 指针使用

指针使用流程:

  • 定义指针变量
  • 为指针变量赋值
  • 访问指针变量中指向地址的值

在指针类型前面加上 * 号(前缀)来获取指针所指向的内容。

使用示例:

package mainimport "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 变量的地址是: 20818a220
ip 变量储存的指针地址: 20818a220
*ip 变量的值: 20

以下几点使用指针的建议:

  • 不要对 mapslicechannel 这类引用类型使用指针;

  • 如果需要修改方法接收者内部的数据或者状态时,需要使用指针;

  • 如果需要修改参数的值或者内部数据时,也需要使用指针类型的参数;

  • 如果是比较大的结构体,每次参数传递或者调用方法都要内存拷贝,内存占用多,这时候可以考虑使用指针;

  • intbool 这样的小数据类型没必要使用指针;

  • 如果需要并发安全,则尽可能地不要使用指针,使用指针一定要保证并发安全;

  • 指针最好不要嵌套,也就是不要使用一个指向指针的指针,虽然 Go 语言允许这么做,但是这会使你的代码变得异常复杂;

4. 指针特点

  1. 在赋值语句中,*p 出现在 = 左边表示是指针声明,*p 出现在 = 右边表示取指针指向的值;

  2. 结构体指针访问结构体字段仍然使用 . 点操作符, Go 不支持 -> 操作符;

  3. Go 不支持指针的运算;

  4. 函数中允许返回变量的地址;

package mainimport "fmt"// Phone is struct type 注释开头必须是 结构体或者方法的名字,后面再加空格
type Phone struct { //exported type Phone should have comment or be unexportedgo-lintmodel stringcolor stringprice int
}func main() {var a *int = nilvar b *intc := 10b = &ce := *bphone := Phone{"huawei", "blue", 1000}p := &phone// p++  invalid operation: p++ (non-numeric type *Phone)fmt.Printf("a is %v, a type is %T\n", a, a)fmt.Printf("b is %v, b type is %T\n", b, b)fmt.Printf("e is %v, e type is %T\n", e, e)fmt.Printf("p is %v, p type is %T\n", p, p)fmt.Printf("p.model is %v, p.price is %v\n", p.model, p.price)result := sum(5, 3)fmt.Printf("result is %v, result type is %T\n", *result, result)}func sum(a, b int) *int {ret := a + breturn &ret
}

输出结果:

a is <nil>, a type is *int
b is 0xc000016068, b type is *int
e is 10, e type is int
p is &{huawei blue 1000}, p type is *main.Phone
p.model is huawei, p.price is 1000
result is 8, result type is *int
  1. 对变量进行取地址操作使用 &操作符,可以获得这个变量的指针变量;

  2. 对指针变量进行取值操作使用 *操作符,可以获得指针变量指向的原变量的值;

5. Go 空指针

当一个指针被定义后没有分配到任何变量时,它的值为 nilnil 指针也称为空指针。 nil 在概念上和其它语言的 nullNonenilNULL 一样,都指代零值或空值。

空指针值为 nil,即没有内存地址,是不能进行赋值操作的,比如下面的示例:

var intP *int
*intP =10

运行的时候会提示 invalid memory address or nil pointer dereference。这时候该怎么办呢?其实只需要通过 new 函数给它分配一块内存就可以了,如下所示:

var intP *int = new(int)
//更推荐简短声明法,这里是为了演示
//intP:=new(int)

一个指针变量通常缩写为 ptr 。空指针判断方法:

if(ptr != nil)     /* ptr 不是空指针 */
if(ptr == nil)    /* ptr 是空指针 */

使用示例:

package mainimport "fmt"func main() {var  ptr *intfmt.Printf("ptr 的值为 : %x\n", ptr  )
}

输出结果为:

ptr 的值为 : 0

6. Go 指针数组

ptr 为整型指针数组。因此每个元素都指向了一个值。以下实例的三个整数将存储在指针数组中:

package mainimport "fmt"const MAX int = 3func main() {a := []int{10,100,200}var i intvar ptr [MAX]*int;       // 声明了整型指针数组for  i = 0; i < MAX; i++ {ptr[i] = &a[i] /* 整数地址赋值给指针数组 */}for  i = 0; i < MAX; i++ {fmt.Printf("a[%d] = %d\n", i,*ptr[i] )}
}

7. Go 指向指针的指针

如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。当定义一个指向指针的指针变量时,第一个指针存放第二个指针的地址,第二个指针存放变量的地址:

访问指向指针的指针变量值需要使用两个 * 号,如下所示:

package mainimport "fmt"func main() {var a intvar ptr *intvar pptr **inta = 3000/* 指针 ptr 地址 */ptr = &a/* 指向指针 ptr 地址 */pptr = &ptr/* 获取 pptr 的值 */fmt.Printf("变量 a = %d\n", a )fmt.Printf("指针变量 *ptr = %d\n", *ptr )fmt.Printf("指向指针的指针变量 **pptr = %d\n", **pptr)
}

8. Go 指针作为函数参数

Go 语言允许向函数传递指针,只需要在函数定义的参数上设置为指针类型即可。

ackage mainimport "fmt"func main() {/* 定义局部变量 */var a int = 100var b int= 200fmt.Printf("交换前 a 的值 : %d\n", a )fmt.Printf("交换前 b 的值 : %d\n", b )/* 调用函数用于交换值* &a 指向 a 变量的地址* &b 指向 b 变量的地址*/swap(&a, &b);fmt.Printf("交换后 a 的值 : %d\n", a )fmt.Printf("交换后 b 的值 : %d\n", b )
}func swap(x *int, y *int) {var temp inttemp = *x    /* 保存 x 地址的值 */*x = *y      /* 将 y 赋值给 x */*y = temp    /* 将 temp 赋值给 y */
}

Go 学习笔记(13)— 指针定义、指针特点、空指针、指针数组、指向指针的指针、指针作为函数入参相关推荐

  1. mybatis学习笔记(13)-延迟加载

    2019独角兽企业重金招聘Python工程师标准>>> mybatis学习笔记(13)-延迟加载 标签: mybatis [TOC] resultMap可以实现高级映射(使用asso ...

  2. opencv进阶学习笔记13:图像形态学操作大全(膨胀,腐蚀,开闭,黑帽,顶帽,梯度)python版

    基础版学习笔记: python3+opencv学习笔记汇总目录(适合基础入门学习) 进阶版笔记目录链接: python+opencv进阶版学习笔记目录(适合有一定基础) 基础版形态学: opencv学 ...

  3. mysql分页概念_MySQL学习笔记之数据定义表约束,分页方法总结

    本文实例讲述了MySQL学习笔记之数据定义表约束,分页方法.分享给大家供大家参考,具体如下: 1. primary key 主键 特点:主键是用于唯一标识一条记录的约束,一张表最多只能有一个主键,不能 ...

  4. Linux学习笔记13

    Linux学习笔记13 Linux学习笔记13 配置Nagios 基本介绍 Nagios安装 - 服务端 Nagios安装 - 客户端 监控中心添加被监控主机 配置文件的简单说明 继续添加需要服务端通 ...

  5. 台大李宏毅Machine Learning 2017Fall学习笔记 (13)Semi-supervised Learning

    台大李宏毅Machine Learning 2017Fall学习笔记 (13)Semi-supervised Learning 本博客参考整理自: http://blog.csdn.net/xzy_t ...

  6. 【计算机网络学习笔记13】交换技术(下)

    [计算机网络学习笔记13]交换技术(下) 一.生成树的诞生和发展 1. 环路问题 两个网桥之间的连接网线如果只有一根,而这根网线或者接口有问题,网络就会出现单点故障.所以为了提高可靠性,网桥在互连时一 ...

  7. Hadoop学习笔记—13.分布式集群中节点的动态添加与下架

    Hadoop学习笔记-13.分布式集群中节点的动态添加与下架 开篇:在本笔记系列的第一篇中,我们介绍了如何搭建伪分布与分布模式的Hadoop集群.现在,我们来了解一下在一个Hadoop分布式集群中,如 ...

  8. java 量化指标_量化投资学习笔记13——各种指标的绘图、计算及交易策略

    <量化投资:以python为工具>第五部分笔记 先来画k线图,要注意finance模块已经从matplotlib库中去除,现在要用mpl_finance库,单独安装. 其中有candles ...

  9. R语言小白学习笔记13—基本统计

    R语言小白学习笔记13-基本统计 笔记链接 学习笔记13-基本统计 13.1 概括性统计量 13.2 相关系数和协方差 13.3 t-检验 13.3.1 单样本t检验 13.3.2 两样本t检验 13 ...

  10. Excel VBA 学习笔记13:单元格的格式

    Excel VBA 学习笔记13:单元格的格式 NumberFormat 属性 (Excel) vba excel 单元格格式设置 Excel VBA 单元格格式 python解决SNIMissing ...

最新文章

  1. 如何有效使用Project(1)——编制进度计划、保存基准
  2. python—多线程之数据混乱问题
  3. nodejs开发游戏服务器遇到的性能问题
  4. DICOM文件格式与编程(转)
  5. silverlight 使用IValueConverter 转换
  6. mysql8 php7_在centos7安装nginx+mysql8+php7(LNMP)
  7. 计算机图形标定学,计算机图形学(璩柏青)第10章空间形体的三维重建与图像处理.ppt...
  8. HDU 1492 The number of divisors(约数) about Humble Numbers
  9. Spark提交 指定 kerberos 认证信息
  10. QTP中VBS脚本下FSO、WSH的应用(二)
  11. windows nginx 停止和启动_nginx在window与linux中启动、停止、与关闭
  12. 搜索指定期刊下的领域相关文章
  13. socket,ioctl获取ip
  14. 修复Linux系统内核TCP漏洞,Linux 内核中TCP SACK机制远程Dos漏洞处理方法(CVE-2019-11477) | 聂扬帆博客...
  15. pccad 电气元件_CAD电气元件库谁有?
  16. Selenium使用之——键盘操作方法
  17. 阿里巴巴牵手福特 共同打造智联网汽车
  18. tk域名管理后台_TK域名解析教程,dns设置教程
  19. Origin | 堆叠柱状图 | 多列(分组)堆积柱状图
  20. 终于明白为什么人人都爱Django了,Django果然天下第一

热门文章

  1. 2022-2028年中国铁路机车行业投资分析及前景预测报告
  2. 取消打开命令行进入默认anaconda的环境
  3. PyTorch官方中文文档:torch.optim 优化器参数
  4. LeetCode中等题之特殊等价字符串组
  5. LeetCode简单题之设计 Goal 解析器
  6. LeetCode简单题之寻找比目标字母大的最小字母
  7. MySQL最新版8.0.21安装配置教程~
  8. Error: Gradle project sync failed. Please fix your project and try again.
  9. Android intent 接受值的内容为空
  10. Android 多渠道打包