【Go指针详解】

什么是指针

众所周知,程序运行时的数据是放在内存中的,而内存会被抽象为一系列具有连续编号的内存空间,那么每一个存储在内存中的数据都会有一个编号,这个编号就是内存地址。有了内存地址就可以找到这个内存中存储的数据,而内存地址可以被赋值给一个指针。

提示: 内存地址通常是16进制的数字表示,比如0x123b2a

在编程语言中,指针是一种数据类型,用来存储一个内存地址,该地址指向存储在该内存中的对象。这个对象可以使字符串、整数、函数或者自定义的结构体。

小技巧: 可以简单的把指针理解为内存地址。

每本书都有目录,目录上会有对应章节的页码,可以把页码理解为一系列的内存地址,通过页码可以快速定位到具体章节(即通过内存地址可以快速找到存储的数据)。

指针的声明和定义

在Go语言中,获取一个变量的指针非常容易,使用取地址符 & 即可。**指针类型非常廉价,只占用4个或8个字节的内存大小。**
func main() {
    name := "奔跑的蜗牛"
    nameP := &name 
    fmt.Println("name变量的值:",name, "name变量的内存地址:", nameP)
}
示例中nameP指针的类型是 ***string**,用于指向 string 类型的数据。在Go语言中使用类型名称前加 * 的方式,即可表示一个对应的指针类型。比如 int 类型的指针类型为 *int,float64 类型的指针类型是 *float64,自定义结构体A的指针类型是 *A。总之,指针类型就是对应的类型前加 * 号。 

提示: 指针变量的值就是它所指向数据的内存地址,普通变量的值就是我们具体存放的值。

不同指针类型是无法相互赋值的,比如不能对一个string类型的变量取地址然后赋值给 *int指针类型,编译器会提示 Cannot user '&name' (type *string) as type *int in assignment。

除了可以通过简短声明的方式声明一个指针类型的变量外,也可以**使用var关键字声明**,格式如下:
var intP *int
intP = &name

// 指针变量和普通变量一样,既可以通过var关键字定义,也可以通过简短声明定义。
**通过var关键字声明的指针变量不能直接复制和取值,因为这个时候它仅仅是一个变量,还没有对应的内存地址,它的值是nil。** 和普通变量不同的是,指针类型还可以通过内置的new函数来声明,如下:

intP1 := new(int)

内置函数new有一个参数,可以传递类型给它。它会返回对应的指针类型。

指针的操作

在Go语言中指针的操作就两种:一种是获取指针指向的值,一种是修改指针指向的值。
nameV := *nameP
fmt.Println("nameP指针指向的值:", nameV)

// 要想获取指针指向的值,只需要在指针变量前加 * 号即可。

*nameP = "独臂阿童木"  //修改指针指向的值
fmt.Println("nameP指针指向的值:", *nameP)
fmt.Println("name变量的值:", name)

// 输出
nameP指针指向的值: 独臂阿童木
name变量的值: 独臂阿童木

// 由此可见,不光namep指针指向的值改变了,变量name的值也改变了,这就是指针。
我们知道通过var关键字直接定义的指针变量是不能直接进行赋值操作的,因为它的值是nil,即还没有指定内存地址。
var intP *int
*intP = 10

// 运行时会提示 invaild  memory address or nil pointer deference。 这个时候只需要通过new函数分配一块内存就可以了

var intp *int = new(int)
// 简短声明法
intP := new(int)

指针参数

age := 18
modifyAge(age)
fmt.Println("age的值:", age)

func modifyAge(a int) {
    a = 19
}

// 上述代码,变量age的值并不会改变成19。因为modifyAge函数中的age只是实参age的一份拷贝,所以修改它不会改变实现age的值。


// 如果要达到修改值的目的,就要使用指针
age := 18 
modifyAge(&age)
fmt.Println("age的值", age)

func modifyAge(a *int){
    *a = 19
}

// 如果要在函数中通过形参改变实参的值,需要使用指针类型的参数

指针接收者

是否使用指针类型作为接收者,需要参考一下几点,但是是否是哟和哪个指针类型作为接收者,需要结合实际情况考虑:
  • 如果接收者类型是map、slece、channel这类引用类型,不使用指针
  • 如果需要修改接收者,那么需要使用指针
  • 如果接收者是比较大的类型,可以考虑使用指针,因为内存拷贝廉价,所以效率高

使用指针的好处

1. 可以修改指向数据的值
2. 在变量赋值、参数传值的时候可以节省内存

指针使用的建议:

  1. 不要对map、slice、channel这类引用类型使用指针
  2. 如果需要修改方法接收者内部的数据或者状态,需要使用指针
  3. 如果需要修改参数的值或者内部数据时,也需要使用指针类型的参数
  4. 如果是比较大的结构体,每次参数产地或者调动方法都要内存拷贝,内存占用多,这时候可以考虑使用指针
  5. 像int、bool这样的小类型数据没必要使用指针
  6. 如果需要并发安全,尽可能的不使用指针,使用指针一定要保证并发安全
  7. 指针最好不要嵌套,也就是不要用一个指向指针的指针,虽然Go语言允许这么做,但是会使代码异常复杂。

总结:为了使编程更简单,指针在高级的语言中逐渐被淡化,但是也确实有自己的优势:修改数据的值和节省内存。所以在Go语言的开发中我们要尽可能的使用值类型,而不是指针类型,因为值类型可以是开发变的更简单,并且是鬓发安全的。如果需要使用指针类型,需要考虑前面的使用条件,是否满足,在满足和必须的情况下才使用指针。


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,427评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,551评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,747评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,939评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,955评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,737评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,448评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,352评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,834评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,992评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,133评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,815评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,477评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,022评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,147评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,398评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,077评论 2 355

推荐阅读更多精彩内容