6 Go语言的常量、枚举、作用域
本专栏将从基础开始,循序渐进,由浅入深讲解Go语言,希望大家都能够从中有所收获,也请大家多多支持。
查看相关资料与知识库
专栏地址:Go专栏
如果文章知识点有错误的地方,请指正!大家一起学习,一起进步。
文章目录
- 常量
- 练习 1.16 – 常量
- 预期输出
 
- 枚举
- 作用域
 
常量
常量类似于变量,但其初始值不能更改。在需要代码运行时保持不变的值的情况下,使用常量非常有用。虽然可以将这些值硬编码到代码中以实现类似效果,但经验表明,虽然这些值在运行时不需要更改,但将来可能需要更改。如果发生这种情况,追踪和修复所有硬编码的值可能是一项繁琐且容易出错的任务。使用常量可以节省大量的后续维护工作。
常量声明类似于 var 语句。定义常量时,必须指定初始值。类型是可选的,如果省略,类型将会被推断。初始值可以是文字值或简单的表达式,并且可以使用其他常量的值。与 var 一样,可以在一个语句中声明多个常量。以下是常量声明的语法:
const <name> <type> = <value>
const (<name1> <type1> = <value1><name2> <type2> = <value2>…<nameN> <typeN> = <valueN>
)
练习 1.16 – 常量
在这个练习中,我们遇到了一个性能问题:我们的数据库服务器太慢了。我们将创建一个自定义内存缓存。我们会使用 Go 的 map 集合类型作为缓存。缓存中可以存储的项目数量有一个全局限制。我们将使用一个 map 来帮助跟踪缓存中的项目数量。我们需要缓存两种类型的数据:书籍和 CD。两者都使用 ID,因此我们需要一种方法来区分共享缓存中的两种类型的项目。我们需要一种方法来设置和获取缓存中的项目。
我们将设置缓存中的最大项目数量。我们还将使用常量添加前缀,以区分书籍和 CD。让我们开始吧:
-  创建一个新的文件夹,并在其中添加一个 main.go 文件。 
-  在 main.go 文件的顶部添加 main 包名: package main
-  导入我们需要的包: import "fmt"
-  创建一个表示全局限制大小的常量: const GlobalLimit = 100
-  创建一个 MaxCacheSize 常量,它是全局限制大小的 10 倍: const MaxCacheSize int = 10 * GlobalLimit
-  创建我们的缓存前缀: const (CacheKeyBook = "book_"CacheKeyCD = "cd_" )
-  声明一个 map 类型的变量,用于存储缓存,其中键和值都是字符串类型: var cache map[string]string
-  创建一个从缓存中获取项目的函数: func cacheGet(key string) string {return cache[key] }
-  创建一个在缓存中设置项目的函数: func cacheSet(key, val string) {
-  在这个函数中,检查 MaxCacheSize 常量,防止缓存超过这个大小: if len(cache)+1 >= MaxCacheSize {return}cache[key] = val }
-  创建一个从缓存中获取书籍的函数: func GetBook(isbn string) string {
-  使用书籍缓存前缀创建一个唯一的键: return cacheGet(CacheKeyBook + isbn) }
-  创建一个将书籍添加到缓存中的函数: func SetBook(isbn string, name string) {
-  使用书籍缓存前缀创建一个唯一的键: cacheSet(CacheKeyBook+isbn, name) }
-  创建一个从缓存中获取 CD 数据的函数: func GetCD(sku string) string {
-  使用 CD 缓存前缀创建一个唯一的键: return cacheGet(CacheKeyCD + sku) }
-  创建一个将 CD 添加到共享缓存中的函数: func SetCD(sku string, title string) {
-  使用 CD 缓存前缀常量为共享缓存构建一个唯一的键: cacheSet(CacheKeyCD+sku, title) }
-  创建 main() 函数: func main() {
-  通过创建一个 map 值来初始化缓存: cache = make(map[string]string) }
-  将一本书添加到缓存中: SetBook("1234-5678", "Get Ready To Go")
-  将 CD 添加到缓存中: SetCD("1234-5678", "Get Ready To Go Audio Book")
-  从缓存中获取并打印那本书: fmt.Println("Book :", GetBook("1234-5678"))
-  从缓存中获取并打印那张 CD: fmt.Println("CD :", GetCD("1234-5678"))
-  关闭 main() 函数: }
-  保存文件。然后,在新文件夹中运行: go run .
预期输出
在这个练习中,我们使用常量来定义在代码运行时不需要更改的值。我们用不同的语法选项声明了常量,有的指定了类型,有的则没有。我们既声明了单个常量,也在一个语句中声明了多个常量。
接下来,我们将查看与常量相关的变体,用于更紧密关联的值。
枚举
枚举是一种定义固定值列表的方式,这些值都是相关的。虽然 Go 语言没有内置的枚举类型,但它提供了 iota 工具,让我们可以使用常量定义自己的枚举。接下来,我们将探讨如何使用 iota 来实现枚举。
例如,在以下代码中,我们将一周的天数定义为常量。这个代码很适合使用 Go 的 iota 特性:
…
const (Sunday  = 0Monday  = 1Tuesday = 2Wednesday = 3Thursday = 4Friday  = 5Saturday = 6
)
…
使用 iota,Go 会帮助我们管理这样的列表。使用 iota,以下代码等同于上面的代码:
…
const (Sunday = iotaMondayTuesdayWednesdayThursdayFridaySaturday
)
…
通过 iota,我们可以自动为枚举分配值。使用 iota 使得创建和维护枚举更加方便,特别是在你需要在代码中间添加新值时。iota 是一个标识符,指示 Go 编译器从 0 开始为第一个值分配,后续值每次递增 1。在使用 iota 时,顺序是重要的。iota 还允许跳过值(使用 _),从不同的偏移量开始,甚至使用更复杂的计算。
接下来,我们将详细了解 Go 的变量作用域规则以及这些规则如何影响代码编写。
作用域
在 Go 中,所有变量都存在于一个作用域中。顶级作用域是包作用域。作用域可以包含子作用域。定义子作用域的方式有几种;最简单的理解方式是,当你看到 { 时,表示你开始了一个新的子作用域,而这个子作用域在遇到匹配的 } 时结束。父子关系是在代码编译时定义的,而不是在代码运行时。当访问变量时,Go 会查看变量定义的作用域。如果在当前作用域找不到该变量,Go 会查看父作用域,然后是祖父作用域,一直到包作用域。当找到匹配的变量时,Go 会停止查找。如果没有找到匹配的变量,则会报错。
换句话说,当你的代码使用一个变量时,Go 需要确定该变量的定义位置。它从当前代码的作用域开始查找。如果在该作用域内找到一个变量定义,则停止查找并使用该变量定义。如果找不到变量定义,则开始向上遍历作用域栈,直到找到具有该名称的变量。这个查找过程基于变量名称。如果找到的变量名称匹配但类型不正确,Go 会抛出错误。
在以下示例中,我们定义了一个 level 变量。无论在哪里使用 level,都会使用同一个变量:
package main
import "fmt"
var level = "pkg"
func main() {fmt.Println("Main start :", level)if true {fmt.Println("Block start :", level)funcA()}
}
func funcA() {fmt.Println("funcA start :", level)
}
输出结果如下:
Main start : pkg
Block start : pkg
funcA start : pkg
在这个示例中,我们创建了一个 level 的影子变量。这个新的 level 变量与包作用域中的 level 变量没有关系。当我们在块内打印 level 时,Go 运行时会在 main 的作用域中找到 level 变量,并停止查找。这导致新变量覆盖了包变量。你也可以看到它是一个不同的变量,因为它的类型不同,变量在 Go 中不能改变类型:
package main
import "fmt"
var level = "pkg"
func main() {fmt.Println("Main start :", level)// 创建一个影子变量level := 42if true {fmt.Println("Block start :", level)funcA()}fmt.Println("Main end :", level)
}
func funcA() {fmt.Println("funcA start :", level)
}
输出结果如下:
Main start : pkg
Block start : 42
funcA start : pkg
Main end : 42
Go 的静态作用域解析在调用 funcA 时发挥作用。因此,当 funcA 运行时,它仍然看到包作用域中的 level 变量。作用域解析不考虑 funcA 的调用位置。
你不能访问子作用域中定义的变量:
package main
import "fmt"
func main() {{level := "Nest 1"fmt.Println("Block end :", level)}// 错误:未定义: level//fmt.Println("Main end  :", level)
}
相关文章:
6 Go语言的常量、枚举、作用域
本专栏将从基础开始,循序渐进,由浅入深讲解Go语言,希望大家都能够从中有所收获,也请大家多多支持。 查看相关资料与知识库 专栏地址:Go专栏 如果文章知识点有错误的地方,请指正!大家一起学习,…...
 
第十一章 数据结构
第十一章 数据结构 11.1 数组 数组是元素的顺序集合,通常这些元素具有相同的数据类型 索引表示元素在数组中的顺序号,顺序号从数组开始处计数 数组元素通过索引被独立给出了地址,数组整体上有一个名称,但每个元素利用数组的的…...
LeetCode704 二分查找
前言 题目: 704.二分查找 文档: 代码随想录——二分查找 编程语言: C 解题状态: 解答错误,变量定义位置错误。 思路 有序数组的查找,最直接的思路应该就是二分查找。但是在查找的过程中要考虑到区间的边界…...
 
[言简意赅] Matlab生成FPGA端rom初始化文件.coe
🎎Matlab生成FPGA端rom初始化文件.coe 本文主打言简意赅。 函数源码 function gencoeInitialROM(width, depth, signal, filepath)% gencoeInitialROM - 生成 Xilinx ROM 初始化格式的 COE 文件%% 输入参数:% width - ROM 数据位宽% depth - ROM 数据深度% s…...
 
【QAC】分布式部署下其他机器如何连接RLM
1、 文档目标 解决分布式部署下其他机器如何连接RLMLicense管理器。 2、 问题场景 分布式部署下QAC要在其他机器上单独运行扫描,必须先连接RLMLicense管理器,如何连接? 3、软硬件环境 1、软件版本:HelixQAC23.04 2、机器环境…...
从等保测评看行业安全趋势:洞察与预测
在当今数字化时代,网络安全已成为各行各业的头等大事。等保测评(等级保护测评),作为国家对信息系统安全的重要管理手段,不仅关乎企业的合规性,更是行业安全水平的重要衡量标准。本文将从等保测评的视角出发…...
 
HTTP模块(二)
HTTP 设置 HTTP 响应报文 HTTP报文常见属性: const http require(http);const server http.createServer((request, response) > {// 设置请求状态码 2xx 4xx 5xxresponse.statusCode 200;// 设置请求描述 了解即可response.statusMessage hello// 指定响…...
引入缓存带来的问题以及解决方案
目录 前言 问题与解决方案 缓存击穿 缓存穿透 缓存雪崩 缓存一致性 前言 在提升接口性能的方案中,毫无疑问,使用缓存是最有效果的,但同时也会带来新的问题。 缓存击穿缓存穿透缓存雪崩缓存一致性 以上问题都是引入缓存需要考虑的&am…...
力扣39题:组合总和的 Java 实现
引言 力扣(LeetCode)是一个在线编程平台,提供了大量的编程题目供开发者练习。第39题“组合总和”是一个经典的回溯算法问题,要求找出所有可能的组合,使得组合中的数字之和等于给定的目标值。本文将介绍如何使用 Java …...
使用el-table实现自动滚动
文章目录 概要技术实现完整代码 概要 在前端开发大屏的时候,我们会用到表格数据展示,有时候为了使用户体验更加好,会增加表格自动滚动。下边我将以示例代码,用element UI的el-table来讲一下。 技术实现 1 .增加dom监听…...
 
Angular由一个bug说起之八:实践中遇到的一个数据颗粒度的问题
互联网产品离不开数据处理,数据处理有一些基本的原则包括:准确性、完整性、一致性、保密性、及时性。 准确性:是数据处理的首要目标,确保数据的真实性和可靠性。准确的数据是进行分析和决策的基础,因此…...
 
day13(DNS域名解析)
今天内容: 1、逆向解析 2、多域名 3、时间服务器 4、主从配置 1.设置逆向解析 (1)永久配置我们自己的DNS服务器 (2)关闭NetworkManager服务 NetworkManager 的自动管理功能可能会干扰定制化的网络配置。 在需要切换…...
 
uboot的mmc partconf命令
文章目录 命令格式参数解释具体命令解释总结 mmc partconf 是一个用于配置 MMC (MultiMediaCard) 分区的 U-Boot 命令。具体来说,这个命令允许你设置或读取 MMC 卡的分区配置参数。让我们详细解释一下 mmc partconf 0 0 1 0 命令的含义。 命令格式 mmc partconf &…...
 
数据结构经典测题3
1. 设有定义: char *p; ,以下选项中不能正确将字符串赋值给字符型指针 p 的语句是【多选】( ) A: pgetchar(); B: scanf("%s",p); C: char s[]"china"; ps; D: *p"china"; 答案为ABD A选项&…...
tensorboard add_text() 停止自动为尖括号标记添加配对的结束括号</>
问题 调用tensorboard的add_text()记录文本信息时,如果文本中含有含尖括号的标记,就会被自动识别为html标记,因此tensorboard会自动生成对应的带斜杠的结束标记。 例如要记录的文本是 abc<abc>,在tensorboard中就会显示为a…...
 
sql-libs通关详解
1-4关 1.第一关 我们输入?id1 看回显,通过回显来判断是否存在注入,以及用什么方式进行注入,直接上图 可以根据结果指定是字符型且存在sql注入漏洞。因为该页面存在回显,所以我们可以使用联合查询。联合查询原理简单说一下&…...
【STM32】当按键具有上拉电阻时GPIO应该配置什么模式?怎么用按键去控制LED翻转?
当按键具有上拉电阻时,可以通过正确配置STM32的GPIO端口和编写相应的控制代码来实现按键控制LED灯的功能。具体来说,需要配置按键所连接的GPIO端口为输入模式,并启用内部上拉电阻,这样在按键未操作时该端口保持高电平状态…...
 
EXO-chatgpt_api 解释
目录 chatgpt_api 解释 resolve_tinygrad_tokenizer 函数 resolve_tokenizer 函数 调试和日志记录 参数 返回值 初始化方法 __init__ 异步方法 注意事项 chatgpt_api 解释 展示了如何在一个项目中组织和导入各种库、模块和类,以及如何进行一些基本的We…...
新能源汽车的充电网络安全威胁和防护措施
1. 物理攻击:例如恶意破坏、搬走充电设施等,这可能会对充电设施造成损害,妨碍正常的电力传输。 2. 网络攻击: 黑客可能利用系统漏洞攻击网络,破坏设备,并窃取用户的个人信息、支付信息等; 车辆…...
Linux中利用消息队列给两个程序切换显示到前台
消息队列–两个进程间的通信 需求: 1.在Linux系统中2.两个ui界面的程序切换,一个显示,另一个隐藏 .h #ifndef PROGRAMWINDOWSWITCH2_H #define PROGRAMWINDOWSWITCH2_H#include <QObject> #include <QThread> #include <Q…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
 
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
 
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
 
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
 
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
 
springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...
