Go语言高并发与微服务实战 - 学习笔记 第3章 Go语言基础 3.3 基本语法 3.3.3 指针

文章介绍了Go语言中的指针概念,如何通过取址符获取变量地址,以及指针类型和取值操作。Go语言限制了指针运算以提高安全性,并通过垃圾回收机制简化内存管理。文中还展示了如何使用指针进行变量赋值及通过new函数分配内存。此外,文章提到了Go的flag包在处理命令行参数时如何使用指针。

Go语言高并发与微服务实战 - 学习笔记

第3章 Go语言基础

3.3 基本语法
3.3.3 指针

在C/C++语言中,指针直接操作内存的特性使得C/C++具备极高的性能,开发人员通过它直接操作和管理大块内存数据。

但与此同时,指针偏移、运算和内存释放可能引发的错误也让指针编程饱受诟病。

Go语言限制了指针类型的偏移和运算能力,使得指针类型具备了指针高效访问的特性,但又不会发生指针偏移,避免了非法修改敏感数据的问题。

同时Go语言中提供的自动垃圾回收机制,也减少了对指针占用内存回收的复杂性。

在G0语言中,指针包含以下三个概念:

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

在程序运行的过程中,每一个变量的值都保存在内存中,变量对应的内存有其特定的地址。

假设某一个变量的类型为T,在Go语言中,我们可以通过取址符号&获取该变量对应内存的地址,生成该变量对应的指针。此时,变量的内存地址即生成的指针的值,指针类型即“*T”,称为T的指针类型,“*”代表指针。

举个例子,Pointer.go 程序,看看运行结果

package main

import "fmt"

func main() {

   // 声明一个string 类型
   str := "Golang is Good"

   // 获取str 的指针
   strPtr := &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", strPtr, strPtr)
}

运行结果:

在这里插入图片描述

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

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

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

运行结果:

在这里插入图片描述

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

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

package main

import "fmt"

func main() {

   // 声明一个string 类型
   str := "Golang is Good"
   // 获取str 的指针
   strPtr := &str
   fmt.Printf("str type is %T, value is %v, address is %p\n", str, str, &str)
   fmt.Printf("strPtr type is %T, value is %v\n", strPtr, strPtr)

   newStr := *strPtr // 获取指针对应变量的值
   fmt.Printf("newStr type is %T, value is %v, and address is %p\n", newStr, newStr, &newStr)

   *strPtr = "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, and value is %v,address is %p\n", str, str, &str)

}

运行结果:

在这里插入图片描述

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

值拷贝会创建新的内存空间,然后将原有变量的值复制到新的内存空间中,形成两个独立的变量。通过指针修改str变量的值并不会影响到newStr,因为这两个变量对应的内存地址不一样。

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

如下例子所示:

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

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

在Go语言的flag包中,命令行参数一般以指针的返回,下面我们执行一个读取命令行参数的例子。

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

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

输入以下的执行参数:

go run FlagTest.go -surname="Ding" -personalName="Jiaxiong" -id=100

运行结果

在这里插入图片描述

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

-id=100

--id=100

-id 100

--id 100

效果都是一样的

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝色的烧烤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值