Go语言结构体和元组全面解析
Go语言中的复合类型与其应用
在编程中,标准类型虽然方便,但无法满足所有需求。Go通过支持结构体和元组类型,为开发者提供了自定义数据类型的能力。本文将介绍如何定义结构体、如何使用指针操作结构体、如何通过元组返回多个值等内容,并结合实际示例展示这些功能的强大之处。
复合类型简介
Go的标准类型,如整型、浮点型等,虽然非常灵活和高效,但它们无法涵盖所有数据需求。当我们需要自定义复杂数据类型时,可以使用结构体。Go语言还提供了类似元组的支持,使得函数可以返回多个值,而无需像C语言那样将它们分组到结构体中。
结构体的使用
数组、切片和映射虽然实用,但它们无法将不同类型的数据聚合在一起。当需要将多个不同类型的变量组合成一个新类型时,结构体便派上用场。结构体的每个元素被称为字段。下面通过一个简单的例子来了解如何定义和使用结构体:
type aStructure struct {person stringheight intweight int
}
这个结构体包含了三种不同的字段:person
、height
和 weight
。可以通过以下方式创建一个结构体变量:
var s1 aStructure
通过字段名称访问结构体中的某个值,例如:s1.person
。
结构体字面量可以这样定义:
p1 := aStructure{"张三", 175, 65}
然而,为了避免记忆字段顺序的麻烦,Go允许我们在定义字面量时通过字段名来初始化:
p1 := aStructure{weight: 65, height: 175}
这种方式更加清晰,不必为每个字段都赋初始值。接下来展示一个更实用的例子。
结构体的实际应用
接下来,我们来看一个更复杂的例子structures.go
,这个程序展示了如何在函数中定义结构体并操作它们。
package main
import ("fmt"
)func main() {type XYZ struct {X intY intZ int}var s1 XYZfmt.Println(s1.Y, s1.Z) // 输出结构体字段Y和Z的值
}
在这个例子中,XYZ
结构体类型被定义在main
函数内部,这意味着它只能在当前函数内使用。虽然通常我们会在全局定义结构体以便整个包使用,但局部定义结构体有助于隔离作用域。
接下来,创建两个结构体实例并打印它们:
p1 := XYZ{23, 12, -2}
p2 := XYZ{Z: 12, Y: 13}
fmt.Println(p1) // 打印结构体p1
fmt.Println(p2) // 打印结构体p2
最后,展示如何将结构体存储在数组中:
pSlice := [4]XYZ{}
pSlice[2] = p1
pSlice[0] = p2
fmt.Println(pSlice) // 打印结构体数组
执行上述程序,输出结果如下:
0 0
{23 12 -2}
{0 13 12}
[{0 13 12} {0 0 0} {23 12 -2} {0 0 0}]
我们可以看到,结构体的零值是根据其字段类型的默认值来设置的。改变p2
的值并不会影响已存储在数组中的结构体。
结构体指针的使用
指针是Go中强大的工具,可以避免复制大量数据。我们来看一个与结构体指针相关的例子pointerStruct.go
。
首先,定义结构体:
package main
import ("fmt"
)type myStructure struct {Name stringSurname stringHeight int32
}
接下来,通过函数创建并返回结构体指针:
func createStruct(n, s string, h int32) *myStructure {if h > 300 {h = 0 // 校验身高是否合法}return &myStructure{n, s, h}
}
这个函数通过返回结构体的指针,避免了结构体的大量复制。也可以直接返回结构体:
func retStructure(n, s string, h int32) myStructure {if h > 300 {h = 0}return myStructure{n, s, h}
}
通过这两种方式创建的结构体,在使用上有一些差异。以下是测试代码:
func main() {s1 := createStruct("李雷", "王花", 180)s2 := retStructure("李雷", "王花", 180)fmt.Println((*s1).Name) // 输出结构体指针指向的Namefmt.Println(s2.Name) // 直接输出结构体的Namefmt.Println(s1) // 打印结构体指针fmt.Println(s2) // 打印结构体
}
运行结果如下:
李雷
李雷
&{李雷 王花 180}
{李雷 王花 180}
使用new
关键字
Go支持使用new
关键字来分配内存,并返回对象的内存地址。例如:
pS := new(aStructure)
通过new
创建的结构体,所有字段的值都被初始化为零值。需要注意的是,new
仅返回对象的指针,而make
则不仅分配内存,还会对切片、映射和通道进行初始化。
元组与多返回值
虽然Go语言不直接支持元组类型,但函数可以返回多个值,具有类似元组的效果。来看一个返回三个值的函数:
package main
import ("fmt"
)func retThree(x int) (int, int, int) {return 2 * x, x * x, -x
}func main() {fmt.Println(retThree(10)) // 输出三个返回值n1, n2, n3 := retThree(20) // 接收返回值fmt.Println(n1, n2, n3)n1, n2 = n2, n1 // 交换值fmt.Println(n1, n2, n3)
}
运行结果:
20 100 -10
40 400 -20
400 40 -20
元组的这种用法非常实用,例如用于交换值,或忽略某些返回值。
结论
通过结构体和元组,Go提供了强大的复合类型支持,让我们能够更好地组织和操作复杂的数据。在实际编程中,充分利用这些特性能够提高代码的可读性和效率。
相关文章:
Go语言结构体和元组全面解析
Go语言中的复合类型与其应用 在编程中,标准类型虽然方便,但无法满足所有需求。Go通过支持结构体和元组类型,为开发者提供了自定义数据类型的能力。本文将介绍如何定义结构体、如何使用指针操作结构体、如何通过元组返回多个值等内容…...

集成电路学习:什么是SDK软件开发工具包
SDK:软件开发工具包 SDK,即Software Development Kit(软件开发工具包),是一套由软件提供商或其他组织提供的开发工具集合。这些工具旨在帮助开发者更快速、更便捷地创建、测试和部署软件应用程序。以下是对SDK的详细解…...
java后端如何发送http请求
用java后端发送请求需要用到的一个工具包为HttpClient。HttpClient是Apache的一个子项目,是高效的、功能丰富的支持HTTP协议的客户端编程工具包。 引入依赖 <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId&…...

装WebVideoCreator记录
背景,需要在docker容器内配置WebVideoCreator环境,配置npm、node.js WebVideoCreator地址:https://github.com/Vinlic/WebVideoCreator 配置环境,使用这个教程: linux下安装node和npm_linux离线安装npm-CSDN博客 1…...
【编程底层思考】什么是GC Roots
在Java虚拟机(JVM)中,GC Roots是垃圾收集(Garbage Collection,GC)过程中的起点,用于确定对象是否可被回收。GC Roots集合是一组必须活跃的(即必须保留在内存中的)引用&am…...

[STL --stack_queue详解]stack、queue,deque,priority_queue,容器适配器
stack stack介绍 1、stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。 2、stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供…...

240907-Gradio插入Mermaid流程图并自适应浏览器高度
A. 最终效果 B. 示例代码 import gradio as grmermaid_code """ <iframe srcdoc <!DOCTYPE html> <html><head><meta charset"utf-8" /><meta name"viewport" content"widthdevice-width" />…...

ubuntu 安装python3 教程
本篇教程,主要介绍如何在Ubuntu上安装python3教程。 1、查看是否有python 在安装前,首先看看自己系统上,是否存在python环境,可能有些系统,默认就安装过python,如果已经有python了,可以直接跳过安装教程。 2、安装步骤 apt update && apt install -y python3 p…...
NOR Flash、NAND Flash……
存储类型描述Compact Flash一种用于便携式电子设备的数据存储设备,于1994年由SanDisk公司推出。SRAM静态随机存取存储器,不需要刷新电路即能保存数据,速度快但集成度低、功耗大。PSRAM伪静态随机存取存储器,结合了SRAM和DRAM的特点…...
【高性能代码】提高代码的性能有哪些方式,如何写出高性能代码,一段代码如何提高这段代码的执行性能,高性能代码开发
【高性能代码】提高代码的性能有哪些方式,如何写出高性能代码,一段代码如何提高这段代码的执行性能,高性能代码开发 提高代码的性能是软件开发中一个重要的方面,尤其是在处理大数据、高并发或实时性要求较高的应用时。以下是一些提…...

2024整理 iptables防火墙学习笔记大全_modepro iptables
Iptables名词和术语 2iptables表(tables)和链(chains) 2表及其链的功能 2 Filter表 2 NAT表 2 MANGLE表 2iptables的工作流程 3iptables表和链的工作流程图 3 二、 iptables实战应用 4iptables命令参数详解 4 iptable…...

实验记录 | 点云处理 | K-NN算法3种实现的性能比较
引言 K近邻(K-Nearest Neighbors, KNN)算法作为一种经典的无监督学习算法,在点云处理中的应用尤为广泛。它通过计算点与点之间的距离来寻找数据点的邻居,从而有效进行点云分类、聚类和特征提取。本菜在复现点云文章过程ÿ…...
【OJ】常用技巧
1. 模版 #include<bits/stdc.h> using namespace std;int main(){ios::sync_with_stdio(false);cin.tie(0);// write herereturn 0; }2. 填充数组 memset是一个字节一个字节填充,如果是使int类型填充非0或者-1就会报错,如 int a[100]; memset(a…...
Redis:Redis性能变慢的原因
一、淘汰策略性能问题 当使用Redis当作缓存使用时,通常会给这个实例设置内存上限maxmemory,然后设置一个数据淘汰策略;如果Redis实例设置了内存上限maxmemory,那么也有可能导致Redis变慢。 原因在于,当Redis内存达到…...

Linux多线程——利用C++模板对pthread线程库封装
文章目录 线程封装主要框架线程启动线程等待其他信息 测试函数 线程封装 我们之前介绍过pthread的线程库,这个线程库主要是基于C语言的void*指针来进行传参和返回 我们使用C的模板对其封装可以让他的使用更加方便,并且经过测试可以让我们更加直观的了解…...

SpringBoot教程(十五) | SpringBoot集成RabbitMq(消息丢失、消息重复、消息顺序、消息顺序)
SpringBoot教程(十五) | SpringBoot集成RabbitMq(消息丢失、消息重复、消息顺序、消息顺序) RabbitMQ常见问题解决方案问题一:消息丢失的解决方案(1)生成者丢失消息丢失的情景解决方案1…...

TensorRT-LLM高级用法
--multi_block_mode decoding phase, 推理1个新token, 平时:按照batch样本,按照head,将计算平均分给所有SM; batch_size*num_heads和SM数目相比较小时:有些SM会空闲;加了--multi_block_mode&…...

文心一言功能新升级:读文档、懂翻译、能识图
9月4日,百度文心一言官网显示,在向全社会开放一周年之际,文心一言进行了功能最新全面升级,同时在周年期间为新老会员增加1个月专业版免费使用体验。 据了解,针对网页版用户需求,文心一言实现了创作内容更加…...
C++机试——走方格的方案
题目 请计算n*m的棋盘格子(n为横向的格子数,m为竖向的格子数)从棋盘左上角出发沿着边缘线从左上角走到右下角,总共有多少种走法,要求不能走回头路,即:只能往右和往下走,不能往左和往…...

Bootstrap 字体图标无法显示问题,<i>标签字体图标无法显示问题
bootstrap fileInput 以及 Bootstrap 字体图标无法显示问题。 今天在用 bootstrap fileInput 插件的时候发现图标无法显示,如下: 查看DOM,发现那些图标是<i>标签做的: 网上的方案 方案1 网上很多人说是我们打乱了boots…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

【堆垛策略】设计方法
堆垛策略的设计是积木堆叠系统的核心,直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法,涵盖基础规则、优化算法和容错机制: 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则: 大尺寸/重量积木在下…...
Python网页自动化Selenium中文文档
1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...
JS红宝书笔记 - 3.3 变量
要定义变量,可以使用var操作符,后跟变量名 ES实现变量初始化,因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符,可以创建一个全局变量 如果需要定义…...

【1】跨越技术栈鸿沟:字节跳动开源TRAE AI编程IDE的实战体验
2024年初,人工智能编程工具领域发生了一次静默的变革。当字节跳动宣布退出其TRAE项目(一款融合大型语言模型能力的云端AI编程IDE)时,技术社区曾短暂叹息。然而这一退场并非终点——通过开源社区的接力,TRAE在WayToAGI等…...

鸿蒙Navigation路由导航-基本使用介绍
1. Navigation介绍 Navigation组件是路由导航的根视图容器,一般作为Page页面的根容器使用,其内部默认包含了标题栏、内容区和工具栏,其中内容区默认首页显示导航内容(Navigation的子组件)或非首页显示(Nav…...