go 语言中的 iota

我们经常会在我们的代码中定义类似以下这些常量:

const (ColorRed   = "Red"ColorGreen = "Green"ColorBlue  = "Blue"
)

在其他时候,我们仅仅关注能把一个东西与其他的做区分。
有些时候,有些时候一件事没有本质上的意义。比如,我们在一个数据库表中存储产品,我们可能不想以 string 存储他们的分类。我们不关注这个分类是怎样命名的,此外,该名字在市场上一直在变化。
那我们仅仅关注它们是怎么彼此区分的就好了。

const (CategoryBooks    = 0CategoryHealth   = 1CategoryClothing = 2
)

我们可以使用 0, 1, 和 2 代替,我们也可以选择 17, 43 和 61。这些值是任意的。
常量是重要的,但是它们很难推断,并且难以维护。在一些语言中像 Ruby 开发者通常只是避免它们。在 Go,常量有许多微妙之处。当用好了,可以使得代码非常优雅且易维护的。

自增长

在 Go 中,一个方便的习惯就是使用 iota 标识符,它简化了常量用于增长数字的定义,给以上相同的值以准确的分类。

const (CategoryBooks    = iota // 0CategoryHealth          // 1CategoryClothing        // 2
)

自定义类型

自增长常量经常包含一个自定义类型,允许你依靠编译器。

type Stereotype intconst (TypicalNoob           Stereotype = iota // 0TypicalHipster                          // 1TypicalUnixWizard                       // 2TypicalStartupFounder                   // 3
)

如果一个函数以 int 作为它的参数而不是 Stereotype,如果你给它传递一个 Stereotype,它将在编译器期出现问题。

type Stereotype intconst (TypicalNoob           Stereotype = iota // 0TypicalHipster                          // 1TypicalUnixWizard                       // 2TypicalStartupFounder                   // 3
)func CountAllTheThings(i int) string {return fmt.Sprintf("there are %d things", i)
}func tc() {n := TypicalHipsterfmt.Println(CountAllTheThings(n))
}// output:
// cannot use TypicalHipster (type Stereotype) as type int in argument to CountAllTheThings

相反亦是成立的。给一个函数以 Stereotype 作为参数,你不能给它传递 int。

type Stereotype intconst (TypicalNoob           Stereotype = iota // 0TypicalHipster                          // 1TypicalUnixWizard                       // 2TypicalStartupFounder                   // 3
)func SoSayethThe(character Stereotype) string {var s stringswitch character {case TypicalNoob:s = "I'm a confused ninja rockstar."case TypicalHipster:s = "Everything was better we programmed uphill and barefoot in the snow on the SUTX 5918"case TypicalUnixWizard:s = "sudo grep awk sed %!#?!!1!"case TypicalStartupFounder:s = "exploit compelling convergence to syndicate geo-targeted solutions"}return s
}func tc() {i := 2fmt.Println(SoSayethThe(i))
}// output:
// cannot use i (type int) as type Stereotype in argument to SoSayethThe

这是一个戏剧性的转折,尽管如此。你可以传递一个数值常量,然后它能工作。

func tc() {fmt.Println(SoSayethThe(0))
}// output:
// I'm a confused ninja rockstar.

这是因为常量在 Go 中是弱类型直到它使用在一个严格的上下文环境中。

Skipping Values

设想你在处理消费者的音频输出。音频可能无论什么都没有任何输出,或者它可能是单声道,立体声,或是环绕立体声的。
这可能有些潜在的逻辑定义没有任何输出为 0,单声道为 1,立体声为 2,值是由通道的数量提供。
所以你给 Dolby 5.1 环绕立体声什么值。
一方面,它有6个通道输出,但是另一方面,仅仅 5 个通道是全带宽通道(因此 5.1 称号 - 其中 5.1 表示的是低频效果通道)。
不管怎样,我们不想简单的增加到 3。
我们可以使用下划线跳过不想要的值。

type AudioOutput intconst (OutMute   AudioOutput = iota // 0OutMono                      // 1OutStereo                    // 2__OutSurround // 5
)

表达式

iota 可以做更多事情,而不仅仅是 increment。更精确地说,iota 总是用于 increment,但是它可以用于表达式,在常量中的存储结果值。

type Allergen intconst (IgEggs         Allergen = 1 << iota // 1 << 0 which is 00000001IgChocolate                         // 1 << 1 which is 00000010IgNuts                              // 1 << 2 which is 00000100IgStrawberries                      // 1 << 3 which is 00001000IgShellfish                         // 1 << 4 which is 00010000
)

这个工作是因为当你在一个 const 组中仅仅有一个标示符在一行的时候,它将使用增长的 iota 取得前面的表达式并且再运用它,。在 Go 语言的 spec 中, 这就是所谓的隐性重复最后一个非空的表达式列表。
如果你对鸡蛋,巧克力和海鲜过敏,把这些 bits 翻转到 “on” 的位置(从左到右映射 bits)。然后你将得到一个 bit 值 00010011,它对应十进制的 19。

type Allergen intconst (IgEggs         Allergen = 1 << iota // 1 << 0 which is 00000001IgChocolate                         // 1 << 1 which is 00000010IgNuts                              // 1 << 2 which is 00000100IgStrawberries                      // 1 << 3 which is 00001000IgShellfish                         // 1 << 4 which is 00010000
)func tc() {fmt.Println(IgEggs | IgChocolate | IgShellfish)// output:// 19
}

这是在 Effective Go 中一个非常好定义数量级的示例:

type ByteSize float64const (_           = iota             // ignore first value by assigning to blank identifierKB ByteSize = 1 << (10 * iota) // 1 << (10*1)MB                             // 1 << (10*2)GB                             // 1 << (10*3)TB                             // 1 << (10*4)PB                             // 1 << (10*5)EB                             // 1 << (10*6)ZB                             // 1 << (10*7)YB                             // 1 << (10*8)
)

但是等等,这有更多

当你在把两个常量定义在一行的时候会发生什么?

Banana 的值是什么? 2 还是 3? Durian 的值又是?

const (Apple, Banana = iota + 1, iota + 2Cherimoya, DurianElderberry, Fig
)

iota 在下一行增长,而不是立即取得它的引用。

// Apple: 1 
// Banana: 2 
// Cherimoya: 2 
// Durian: 3 
// Elderberry: 3 
// Fig: 4

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

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

相关文章

【Leetcode】240. 搜索二维矩阵 II

一、题目 1、题目描述 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性: 每行的元素从左到右升序排列。每列的元素从上到下升序排列。示例1: 输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21…

Pytorch:torch.nn.Module.apply用法详解

torch.nn.Module.apply 是 PyTorch 中用于递归地应用函数到模型的所有子模块的方法。它允许对模型中的每个子模块进行操作&#xff0c;比如初始化权重、改变参数类型等。 以下是关于 torch.nn.Module.apply 的示例&#xff1a; 1. 语法 Module.apply(fn)Module&#xff1a;P…

【REST2SQL】05 GO 操作 达梦 数据库

【REST2SQL】01RDB关系型数据库REST初设计 【REST2SQL】02 GO连接Oracle数据库 【REST2SQL】03 GO读取JSON文件 【REST2SQL】04 REST2SQL第一版Oracle版实现 信创要求用国产数据库&#xff0c;刚好有项目用的达梦&#xff0c;研究一下go如何操作达梦数据库 1 准备工作 1.1 安…

ros2 基础学习 15- URDF:机器人建模方法

URDF&#xff1a;机器人建模方法 ROS是机器人操作系统&#xff0c;当然要给机器人使用啦&#xff0c;不过在使用之前&#xff0c;还得让ROS认识下我们使用的机器人&#xff0c;如何把一个机器人介绍给ROS呢&#xff1f; 为此&#xff0c;ROS专门提供了一种机器人建模方法——…

2024华为OD机试:最多几个直角三角形

题目描述 有N条线段&#xff0c;长度分别为a[1]-a[n]。 现要求你计算这N条线段最多可以组合成几个直角三角形。每条线段只能使用一次&#xff0c;每个三角形包含三条线段。 输入描述 第一行输入一个正整数T(1<T<100),表示有T组测试数据.对于每组测试数据&#xff0c;…

软件测试|SQL中的UNION和UNION ALL详解

简介 在SQL&#xff08;结构化查询语言&#xff09;中&#xff0c;UNION和UNION ALL是用于合并查询结果集的两个关键字。它们在数据库查询中非常常用&#xff0c;但它们之间有一些重要的区别。在本文中&#xff0c;我们将深入探讨UNION和UNION ALL的含义、用法以及它们之间的区…

Ubuntu 22.04 编译安装 Qt mysql驱动

参考自 Ubuntu20.04.3 QT5.15.2 MySQL驱动编译 Ubuntu 18.04 编译安装 Qt mysql驱动 下边这篇博客不是主要参考的, 但是似乎解决了我的难题(找不到 libmysqlclient.so) ubuntu18.04.2 LTS 系统关于Qt5.12.3 无法加载mysql驱动&#xff0c;需要重新编译MYSQL数据库驱动的问题以…

【代码随想录】刷题笔记Day45

前言 早上又赖了会床......早睡早起是奢望了现在&#xff0c;新一年不能这样&#xff01;支棱起来&#xff01; 377. 组合总和 Ⅳ - 力扣&#xff08;LeetCode&#xff09; 这一题用的就是完全背包排列数的遍历顺序&#xff1a;先背包再物品&#xff0c;从前往后求的也是有几…

IO类day01

File类 File类的每一个实例可以表示硬盘(文件系统)中的一个文件或目录(实际上表示的是一个抽象路径) 使用File可以做到: 1:访问其表示的文件或目录的属性信息,例如:名字,大小,修改时间等等 2:创建和删除文件或目录 3:访问一个目录中的子项 但是File不能访问文件数据. pu…

mac电脑php命令如何设置默认的php版本

前提条件&#xff1a;如果mac电脑还没安装多个PHP版本&#xff0c;可以先看这篇安装一下 mac电脑运行多个php版本_mac 同时运行两个php-CSDN博客 第一部分&#xff1a;简单总结 #先解除现在默认的php版本 brew unlink php7.4#再设置的想要设置的php版本 brew link php8.1第二部…

AWS Simple Email Service (SES) 实战指南

Amazon Simple Email Service (SES) 是一项强大的电子邮件发送服务&#xff0c;适用于数字营销、应用程序通知以及事务性邮件。在这个实战指南中&#xff0c;我们将演示如何设置 AWS SES 并通过几个示例展示其用法。 设置 AWS SES 1. 创建 AWS 账户 首先&#xff0c;您需要创…

c++学习:容器list实战(获取目录返回容器list)

新建一个dir.h,声明dir类 #ifndef DIR_H #define DIR_H#include <sys/types.h>#include <dirent.h> #include <stdio.h> #include <string.h>#include <iostream> #include <list>class Dir { public:Dir();static std::list<std::str…

Java20:反射

1. 概念2. 获取成员变量2.1 获取public修饰的成员变量2.2 获取已声明的属性 3.获取方法3.1 获取public修饰的&#xff0c;和继承自父类的 方法3.2 获取本类中定义的方法 4. 获取构造器4.1 获取所有public修饰的构造器4.2 获取本类中定义的构造器 5.jdk文件分析5.1bin目录&#…

CodeGPT,你的智能编码助手—CSDN出品

CodeGPT是由CSDN打造的一款生成式AI产品&#xff0c;专为开发者量身定制。 无论是在学习新技术还是在实际工作中遇到的各类计算机和开发难题&#xff0c;CodeGPT都能提供强大的支持。其涵盖的功能包括代码优化、续写、解释、提问等&#xff0c;还能生成精准的注释和创作相关内…

Git、GitHub、Gitee 和 GitLab的区别和使用方法

介绍 Git Git 是一个免费的、开源的分布式版本控制系统&#xff0c;用于快速高效地处理各种项目。它有本地库、暂存区域和多个工作流分支等特性。你可以在本地使用它管理代码&#xff0c;无需联网。 GitHub GitHub 是一个基于 Git 实现的在线代码仓库&#xff0c;是全球最大…

spring-cloud-starter-alibaba-nacos-config 2022.0 连接 nacos 2.3.0 失败处理

版本 spring-cloud-starter-alibaba-nacos-config: 2022.0.0.0 nacos-server 2.3.0 服务器连接失败 报错&#xff1a; Server check fail, please check server xxx.xxx.xxx.xxx ,port 9848 is available , error {} nacos 2.x 除了主端口(默认为8848)以外新增了三个端口需要…

redis 的安装

目录 关系数据库与非关系型数据库 关系型数据库 非关系型数据库 关系型数据库和非关系型数据库区别 非关系型数据库产生背景 总结 Redis概述 Redis 具有以下几个优点 使用场景 哪些数据适合放入缓存中 Redis为什么这么快 Redis 安装部署 Redis 命令工具 Redis 数…

Vue选择年的组件

代码&#xff1a; <div class"block"><span class"demonstration">年</span><el-date-pickerv-model"value3"type"year"placeholder"选择年"></el-date-picker> </div><script>…

win11 如何切换用户?

第1步&#xff1a;打开其他用户 第2步&#xff1a;添加账户 第3步&#xff1a; 使用新用户登录

鉴源论坛 · 观模丨浅谈Web渗透之信息收集(下)

作者 | 林海文 上海控安可信软件创新研究院汽车网络安全组 版块 | 鉴源论坛 观模 社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区” 信息收集在渗透测试过程中是最重要的一环&#xff0c;“浅谈web渗透之信息收集”将通过上下两篇&#xff0c;对信息收集、…