一文了解 Go 中的指针和结构体

news/2024/5/8 3:11:38/文章来源:https://blog.csdn.net/weixin_44604586/article/details/128040481

一文了解 Go 中的指针和结构体

  • 前言
  • 指针
    • 指针的定义
    • 获取和修改指针所指向变量的值
  • 结构体
    • 结构体定义
    • 结构体的创建方式
  • 小结

耐心和持久胜过激烈和狂热。

前言

前面的两篇文章对 Go 语言的基础语法和基本数据类型以及几个复合数据类型进行介绍,本文将对 Go 里面的指针和结构体进行介绍,也为后续文章做铺垫。

指针

Go 语言中,指针可以简单理解是一个地址,指针类型是依托于某一个类型而存在的,例如 Go 里面的基本数据类型 intfloat64string 等,它们所对应的指针类型为 *int*float64*string等。

指针的定义

  • 语法格式:var 指针变量名 *数据类型 = &变量
    & 为取地址符号,通过 & 符号获取某个变量的地址,然后赋值给指针变量。

    import ("fmt"
    )func main() {var num int = 666var numPtr *int = &numfmt.Println(numPtr)  // num 变量的地址值 0xc00001c098fmt.Println(&numPtr) // 指针变量本身的地址值 0xc00000a028
    }
    

    npmPtr 指针变量指向变量 num0xc00001c098num 变量的地址,0xc00000a028 为指针变量本身的地址值。

    在这里插入图片描述

  • 使用 new(T) 函数创建指针变量

    import ("fmt"
    )func main() {numPtr := new(int)fmt.Println(numPtr)  // 0xc000122058fmt.Println(*numPtr) // 0
    }
    

    new(T) 函数为每个类型分配一片内存,内存单元保存的是对应类型的零值,函数返回一个指针类型。

  • 错误的类型地址赋值

    func main() {var num float64 = 666var numPtr *int = &num // cannot use &num (value of type *float64) as type *int in variable declaration
    }
    

    当指针所依托的类型与变量的类型不一致时,Go 编译器会报错,类型不匹配。

获取和修改指针所指向变量的值

  • 通过指针获取所指向变量的值
    func main() {var num int = 666var numPtr *int = &num// 获取 num 的值fmt.Println(*numPtr) // 666
    }
    
    对指针使用 * 操作符可以获取所指向变量的值。
  • 通过指针修改所指向变量的值
    import ("fmt"
    )func main() {var num int = 666var numPtr *int = &num// 修改 num 的值*numPtr = 555fmt.Println(num) // 555
    }
    
    同时也可以对指针使用 * 操作符修改所指向变量的值。

结构体

通过上一篇文章,我们了解了数组和切片的特点,它们可以存储一组相同类型的数据,而结构体,它可以由 0 个或多个字段组成,每个字段的数据类型可以一样,也可以不一样。结构体可以表示一个对象,例如:人,人包含的一些字段有姓名、性别和年龄等。

结构体定义

语法格式:

type XXX struct {/*结构体字段定义区域*/
}

XXX 为结构体的名字,下面以人为对象,引入结构体

// Person定义一个人的结构体
type Person struct {// 姓名Name string// 年龄Age int// 性别Sex string// 身份证号idNumber string
}

上述代码定义了人的结构体 Person,包含四个字段,字段的命名规则和变量是一样的,前三个字段首字母大写,可以被包外访问,第四个字段首字母小写,表示只能在包内访问。
除了上述的定义方式以外,结构体里还可以内嵌结构体

// Person 定义一个人的结构体
type Person struct {// 姓名Name string// 年龄Age int// 性别Sex string// 身份证号idNumber string
}// Phone 手机结构体
type Phone struct {// 品牌Brand string// 拥有者Owner Person
}

上述代码定义了 Person 结构体和 Phone 结构体,Phone 结构体拥有两个字段,分别为 Brand 品牌和 Owner 拥有者,Owner 属性的类型,指定为我们所自定义的 Person 结构体。以这种方式定义的结构体字段,我们可以称为嵌入字段(Embedded Field)。也可以将这种字段称为匿名字段。

结构体的创建方式

  • 1、声明一个结构体变量
    // Person 定义一个人的结构体
    type Person struct {// 姓名Name string// 年龄Age int// 性别Sex string// 身份证号idNumber string
    }func main() {var person Personfmt.Println(person.Name)     // ""fmt.Println(person.Age)      // 0fmt.Println(person.Sex)      // ""fmt.Println(person.idNumber) // ""// 修改结构体字段的值person.Name = "chenmingyong"fmt.Println(person.Name) // "chenmingyong"
    }
    • 通过声明一个结构体变量,隐式创建一个结构体变量,这个结构体变量各个字段值默认为零值,也就是对应类型的默认值。
    • 结构体属性的值,可以通过 变量.字段名 的方式获取,同时也可以通过此方式对字段值进行修改。
  • 2、使用复合字面值进行显式初始化结构体对象
    import "fmt"// Person 定义一个人的结构体
    type Person struct {// 姓名Name string// 年龄Age int// 性别Sex string// 身份证号idNumber string
    }func main() {person := Person{"chenmingyong",18,"男","xxxxxxxxx",}fmt.Println(person) // {chenmingyong 18 男 xxxxxxxxx}
    }
    
    • 上述代码根据字段的顺序进行赋值,实际上,Go 语言并不推荐我们用这种方式进行赋值,因为可能会带来一些问题,例如结构体的某个中间的字段被删除或者字段的顺序改变了,那么我们需要维护对应代码,调整赋值的顺序。
    • 上述创建结构体的方式有弊端,因此我们需要换一种方法,如下第三种方法。
  • 3、 使用 field:value 形式的复合字面值进行显式初始化结构体对象
    import "fmt"// Person 定义一个人的结构体
    type Person struct {// 姓名Name string// 年龄Age int// 性别Sex string// 身份证号idNumber string
    }func main() {person := Person{Sex:      "男",Age:      18,Name:     "chenmingyong",idNumber: "xxxxxxxxx",}fmt.Println(person) // {chenmingyong 18 男 xxxxxxxxx}
    }
    
    通过以上的方式,我们就不被字段的顺序所约束了。
  • 4、通过 new(T) 函数创建结构体指针
    // Person 定义一个人的结构体
    type Person struct {// 姓名Name string// 年龄Age int// 性别Sex string// 身份证号idNumber string
    }func main() {person := new(Person)(*person).Name = "chenmignyong"fmt.Println((*person).Name) // chenmignyong// 简化赋值,底层自动转换成 (*person).Age = 18person.Age = 18fmt.Println(person.Age) // 18
    }
    
    前面提到过,访问指针所指向变量的值,需要使用 * 操作符,但在结构体这里有点特殊,如果不加 * 的话,底层会将 person.Age = 18 转成 (*person).Age = 18

小结

本文对指针和结构体进行了介绍,也指出使用指针和结构体时需要注意的一些地方。因为本文是基于了解的层面去写的文章,一些深入的知识并没有提到,然后也没有提到结构体的方法,是因为打算留到后面和函数一起去介绍。

如果本文对你有帮助,欢迎点赞收藏加关注,如果本文有错误的地方,欢迎指出!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_225696.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL索引底层数据结构

索引简介 索引是一个排好序的数据结构,包含着对数据表里所有记录的引用指针,如下图所示。索引文件和数据文件一样都存储在磁盘中,数据库索引的目的是在检索数据库时,减少磁盘读取次数。 常见的索引数据结构包括二叉树、红黑树、…

跬智信息 (Kyligence) 荣获信创“大比武”重要奖项,坚持做大做实国产软件

近日,为期两个月的 2022 信创“大比武”活动圆满闭幕。经过层层筛选和考核,跬智信息 (Kyligence) 凭借“企业级智能多维数据分析解决方案”项目脱颖而出,在整体方案的技术架构、服务体系、安全架构、信创生态等方面得到了评委的高度认可&…

iptables应用大全

iptables四表五链: 1、“四表”是指 iptables 的功能 ——filter 表(过滤规则表):控制数据包是否允许进出及转发 ——nat 表(地址转换规则表):控制数据包中地址转换 ——mangle(修改…

NDK 是什么 | FFmpeg 5.0 编译 so 库

前言 NDK 全称 Native Development Kit,也就是原生开发工具包 ,官网对它有详细的 中文介绍 。可能一说到 NDK 或 JNI ,大家脑子里第一反应就是集成 C/C 。其实 JNI 的含义是 Java Native Interface ,这种接口允许 Java 和其他语言…

ovs vxlan 时延和吞吐

设计云时到底要不要用vxlan,如果用vxlan到底要不要购买比较贵的smart nic做offload,采用软件vxlan还是硬件交换机vxlan,很难决策,这儿简单测试一下,给个参考,资源终究是有限的,成本还是有考虑的…

【HDU No. 2586】 树上距离 How far away ?

【HDU No. 2586】 树上距离 How far away ? 杭电 OJ 题目地址 【题意】 有n 栋房屋,由一些双向道路连接起来。 每两栋房屋之间都有一条独特的简单道路(“简单”意味着不可以通过两条道路去一个地方)。人们每天总是喜欢这样问&a…

Linux 软链接 与 硬链接 的区别

Linux 软链接 与 硬链接 的区别 1、概念 ​  链接文件:是 Linux 操作系统中的一种文件,主要用于解决文件的共享使用问题,而链接的方式分为两种——软链接和硬链接。 ​  inode:是文件系统中存储文件元信息(文件的…

3.71 OrCAD新建原理图时,每一个类目的含义是什么?OrCAD软件怎么显示元器件的封装名称?

笔者电子信息专业硕士毕业,获得过多次电子设计大赛、大学生智能车、数学建模国奖,现就职于南京某半导体芯片公司,从事硬件研发,电路设计研究。对于学电子的小伙伴,深知入门的不易,特开次博客交流分享经验&a…

Word处理控件Aspose.Words功能演示:在 Python 中将 Word 文档转换为 PNG、JPEG 或 BMP

MS Word 文件到图像格式的转换让您可以将文档的页面嵌入到您的 Web 或桌面应用程序中。为了在 Python 应用程序中执行此转换,本文介绍了如何使用 Python 将 Word DOCX或DOC文件转换为PNG、JPEG或BMP图像。此外,您将学习如何使用不同的选项控制 Word 到图…

SpringBoot2.7.4整合Redis

目录 一、添加maven依赖 二、添加配置项 三、新增配置类 四、编辑实体类 五、编写接口 六、编写业务层 1.编写service层 2.编写service实现层 七、测试接口 一、添加maven依赖 <dependency><groupId>org.springframework.boot</groupId><artif…

Python测试框架之Pytest基础入门

Pytest简介 Pytest is a mature full-featured Python testing tool that helps you write better programs.The pytest framework makes it easy to write small tests, yet scales to support complex functional testing for applications and libraries. 通过官方网站介绍…

Flink部署之Yarn

Flink部署之Yarn 一、环境准备 1、Flink 是一个分布式的流处理框架&#xff0c;所以实际应用一般都需要搭建集群环境。 需要准备 3 台 Linux 机器。具体要求如下&#xff1a; 系统环境为 CentOS 7.5 版本。安装 Java 8。安装 Hadoop 集群&#xff0c;Hadoop 建议选择 Hadoop…

【代码随想录】二刷-二叉树

# 二叉树《代码随想录》 二叉树的遍历方式 深度优先遍历: 前序遍历(递归法、迭代法): 中左右中序遍历(递归法、迭代法): 左中右后序遍历(递归法、迭代法): 左右中 广度优先遍历: 层序遍历(迭代法) 二叉树的定义 struct TreeNode{int val;TreeNode* left;TreeNode* right;Tree…

React - Ant Design3.x版本安装使用,并按需引入和自定义主题

React - Ant Design3.x版本安装使用&#xff0c;并按需引入和自定义主题一. 安装使用 antd二&#xff0e;antd 高级配置安装 react-app-rewired&#xff0c;对 create-react-app 的默认配置进行自定义安装 babel-plugin-import &#xff0c;按需加载组件代码和样式自定义主题An…

[毕业设计]机器学习水域检测标注算法

前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科同学来说是充满挑战。为帮助大家顺利通过和节省时间与精力投…

IO模型Netty

一、IO模型 对于一次IO操作&#xff0c;数据会先拷贝到内核空间中&#xff0c;然后再从内核空间拷贝到用户空间中&#xff0c;所以一次read操作&#xff0c;会经历以下两个阶段&#xff0c;基于这两个阶段就产生了五种不同的IO模式。 为了避免用户进程直接操作内核&#xff0c;…

Android8.1 MTK 浏览器下载的apk点击无反应不能安装

最近测试人员发现用原生浏览器下载的apk点击安装时无反应&#xff0c;不能安装。 在/vendor/mediatek/proprietary/packages/apps/Browser/src/com/android/browser/DownloadHandler.java 中&#xff0c;发现下载的apk文件缺少了mime类型&#xff0c;如下图 mimetype null造…

RS编码译码误码率性能matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法描述 纠错编码技术在卫星通信、移动通信及数字存储等领域已获得了广泛的应用。RS码作为其中最重要的码类之一,具有优良的纠随机错误和突发错误的能力,被空间数据系统咨询委员会(CCSDS)作为一种…

计算机毕业设计——基于SpringBoot框架的网上购书系统的设计与实现

文章目录前言一、背景及意义选题背景选题目的二、系统设计主要功能运行环境三、系统实现部分页面截图展示部分代码展示四、源码获取前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 二十一世纪是网络化&#xff0c;信息化的时代&#xff0c;为了满足广大…

植入“人工心脏”助患者重获“心”生

【同期】人工心脏移植患者 刘女士这要是在过去的时候也就放弃了&#xff0c;我再活20年&#xff0c;我还能看着我大孙子成家&#xff0c;这就是我最大的希望。【解说】11月22日&#xff0c;人工心脏移植患者和心脏移植患者在即将康复出院前&#xff0c;互相握手庆贺。据了解&am…