专栏首页aoho求索Go 语言入门系列:指针的基本应用

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

前文概览

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

指针

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

指针只要包含三个概念:

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

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

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

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

执行结果如下:

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

}

输出的结果为:

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 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 方法,获取命令行参数的值。输入以下的执行参数:

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关键字可以声明常量,声明常量的样式与声明变量非常相似。

本文分享自微信公众号 - aoho求索(aohoBlog),作者:cangwu

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-06-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Go语言入门系列(五)之指针和结构体的使用

    我们写的代码都存储在外存(C盘、D盘)中,比如我存在了D:\Work\Program\go目录下。如果你想要运行你的代码,必须先把你的代码加载进内存中,然后交给...

    二十二画程序员
  • C语言入门系列之8.指针的概念与应用

    指针是C语言中的一个重要的概念,也是C语言的一个重要特色。 正确而灵活地运用它,可以有效地表示复杂的数据结构;能动态分配内存;能方便地使用字符串;有效而方便地...

    cutercorley
  • Go 语言入门系列:切片的应用实践

    Golang 中以标准库的方式提供了常用的容器实现,基本能够满足我们日常开发的需要。我们来具体学习下 Go 数组的使用。

    aoho求索
  • Go 语言基础入门教程 —— 数据类型篇:指针的概念和基本使用

    我们知道,变量的本质对一块内存空间的命名,可以通过引用变量名来使用这块内存空间存储的值,而指针的含义则指向存储这些变量值的内存地址。和 PHP、Java 不同,...

    学院君
  • Go 语言入门系列:数组的使用

    前面的文章主要介绍了 Go 基于语法中的分支和循环控制结构。其中涉及到的 If 、Switch 和 for 等关键字,是我们日常编码所常用的。当我们在程序中操作...

    aoho求索
  • Go语言入门系列(四)之map的使用

    map是一种映射,可以将键(key)映射到值(value),格式为:map[keyType]valueType。

    二十二画程序员
  • Go 语言基础入门系列教程 —— 预热篇

    Go 语言又称 Golang,由 Google 公司于 2009 年发布,近几年伴随着云计算、微服务、分布式的发展而迅速崛起,跻身主流编程语言之列,和 Java...

    学院君
  • Go语言入门系列(七)之如何使用Go的方法?

    如果你用过面向对象的语言,比如Java,那你肯定对类、对象、成员变量、方法等很熟悉。

    二十二画程序员
  • Golang 入门系列(三)Go语言基础知识汇总

    前面已经了 Go 环境的配置和初学Go时,容易遇到的坑,大家可以请查看前面的文章 https://www.cnblogs.com/zhangweizhong/c...

    架构师精进
  • Go 语言入门系列:基本语法介绍之变量的声明与初始化

    前面的文章介绍了 Go 相关的特性与入门案例,对于一门编程语言,变量和语法是我们首先需要掌握的。Go 在语法上与 C 语言有很多相似支持,但是比 C 语言更加简...

    aoho求索
  • Go 语言入门系列:Go 语言中的常量别名与控制结构

    前面一篇文章主要介绍了 Go 语言中的指针基本概念与相关用法。Go 语言限制了指针类型的偏移和运算能力,使得指针类型具备了指针高效访问的特性,但又不会发生指针偏...

    aoho求索
  • 【Go语言入门系列】Go语言工作目录介绍及命令工具的使用

    在【保姆级教程】手把手教你进行Go语言环境安装及相关VSCode配置一文中已经配置过工作空间GOPATH的环境变量了,并在工作空间中新建了三个目录src、pkg...

    二十二画程序员
  • Golang 入门系列(二)Go语言基础语法及需要注意的坑

    上一章节我们已经了解了 Go 环境的配置,不了解的,请查看前面的文章 https://www.cnblogs.com/zhangweizhong/p/94599...

    架构师精进
  • Go 语言网络编程系列(九)—— JSON 处理篇:JSON 编解码基本使用入门

    Go 语言内置了 encoding/json 标准库对 JSON 进行支持,开发者可以通过它轻松生成和解析 JSON 格式数据,下面我们来简单演示下这个库的使用...

    学院君
  • Golang 入门系列(五)GO语言中的面向对象

    其实GO并不是一个纯面向对象编程语言。它没有提供类(class)这个关键字,只提供了结构体(struct)类型。

    架构师精进
  • Go 语言 Web 编程系列(一)—— 快速入门:创建第一个 Web 应用

    首先,我们基于 HTTP 编程中介绍的 net/http 包来实现一个简单的 HTTP 服务器作为 Web 服务器:

    学院君
  • Go语言入门系列(六)之再探函数

    在Go语言入门系列(二)之基础语法总结这篇文章中已经介绍过了Go语言的函数的基本使用,包括声明、参数、返回值。本文再详细介绍一下函数的其他使用。

    二十二画程序员
  • 适合 Go 新手学习的开源项目——在 GitHub 学编程

    故事要从 2007 年说起。因为受够了 C++ 煎熬的 Google 首席软件工程师 Rob Pike 召集 Robert Griesemer 和 Ken Th...

    HelloGitHub
  • [GO语言基础] 一.为什么我要学习Golang以及GO语言入门普及

    作为网络安全初学者,会遇到采用Go语言开发的恶意样本。因此从今天开始从零讲解Golang编程语言,一方面是督促自己不断前行且学习新知识;另一方面是分享与读者,希...

    Eastmount

扫码关注云+社区

领取腾讯云代金券