前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go 语言入门系列:指针的基本应用

Go 语言入门系列:指针的基本应用

作者头像
aoho求索
发布2021-07-16 15:48:40
5370
发布2021-07-16 15:48:40
举报
文章被收录于专栏:aoho求索aoho求索

前文概览

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

指针

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

指针只要包含三个概念:

  • 指针地址
  • 指针类型
  • 指针取值

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

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

代码语言:javascript
复制
package main

import "fmt"

func main()  {
 //声明一个 string 类型
 str := "Golang is Good!"
 //获取 str 的指针
 strPrt := &str

 fmt.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)
}

执行结果如下:

代码语言:javascript
复制
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 进行取址操作,如下所示:

代码语言:javascript
复制
strPtrPtr := &strPrt
fmt.Printf("strPtrPtr type is %T, and value is %v\n", strPtrPtr, strPtrPtr)

它的输出结果为:

代码语言:javascript
复制
strPtrPtr type is **string, and value is 0xc00007a018

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

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

代码语言:javascript
复制
package main

import "fmt"

func main()  {
 str := "Golang is Good!"
 strPrt := &str

 fmt.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)

}

输出的结果为:

代码语言:javascript
复制
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 函数直接分配内存,并返回指向内存的指针,此时内存中的值会被初始化为类型的默认值。如下例子所示:

代码语言:javascript
复制
str := new(string)
*str = "Golang is Good!"

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

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

代码语言:javascript
复制
package main

import (
 "flag"
 "fmt"
)

func main()  {
 //定义一个类型为 string,名称为 surname 的命令行参数
 //参数依次是命令行参数的名称,默认值,提示
 surname := flag.String("surname", "王", "您的姓")
 //定义一个类型为 string,名称为 personalName 的命令行参数
 //除了返回指针类型结果,还可以直接传入变量地址获取参数值
 var personalName string
 flag.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 方法,获取命令行参数的值。输入以下的执行参数:

代码语言:javascript
复制
go run Flag.go -surname="苍" -personalName="小屋" -id=100

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

代码语言:javascript
复制
-id=100
--id=100
-id 100
--id 100

输出结果如下:

代码语言:javascript
复制
I am 苍 小屋, and my id is 100

小结

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

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-06-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 aoho求索 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前文概览
  • 指针
  • 小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档