【Go语言圣经3.6】

目标

概念

  1. 常量与变量的主要区别在于:
    • 不可变性:常量在声明后其值就固定下来,不能再被修改。这保证了程序运行时不会因意外修改而导致错误。
      • 使用不可变数据(例如数学常数 π)可以避免意外修改带来的问题
    • 编译期计算:常量表达式在编译期间就会被求值,这不仅减少了运行时的计算负担,还意味着许多在运行时可能出错的操作(比如除零、越界)都可以在编译阶段捕获。
  2. Go 中常量的潜在类型为布尔型、字符串或数字
  3. 无类型常量:在定义时没有显式指定类型的常量。比如写 3.140"hello",这些数值或字符串常量在初始状态下没有固定的类型。
  4. 六种无类型常量:分别对应布尔、整数、字符(rune)、浮点数、复数和字符串。
  5. 无类型常量更高精度的运算:无类型常量在算术运算中拥有比具体类型(如 int 或 float64)更高的精度(可以看作有 256 位或更多位的精度);像 ZiB 或 YiB 这样超出任何内置整数类型范围的常量,也仍然可以参与运算(例如 YiB / ZiB),因为在编译期编译器会将它们按照数学上准确的值处理。

要点

常量声明

  1. 声明常量时,可以直接赋予初值:

    
    const pi = 3.14159 // 近似值;实际上 math.Pi 提供了更精确的值
    

    这和变量声明语法类似,但常量的值一旦设定就不能修改。

  2. 批量声明常量

    多个相关常量可以使用小括号一起声明:

    const (e  = 2.71828182845904523536028747135266249775724709369995957496696763pi = 3.14159265358979323846264338327950288419716939937510582097494459
    )

    这样的批量声明不仅代码更简洁,也可以利用类型推断:如果没有显式指定类型,常量的类型会根据右侧的表达式自动推断。

    类型推断说明

    • 如果你在常量声明时没有显式标明类型,则 Go 会根据右边的表达式推断类型。例如:

      const timeout = 5 * time.Minute
      

      此时 timeout 会被推断为 time.Duration 类型,因为 time.Minute 本身是 time.Duration 类型的常量。

编译期常量表达式与优化

在数组定义中,可以用常量来指定数组的长度:

const IPv4Len = 4func parseIPv4(s string) IP {var p [IPv4Len]byte// 解析 IPv4 地址的逻辑
}

这样,数组长度在编译期间就确定下来了。程序运行时减少了不必要的计算,提高了效率。

iota常量生成器

  1. iota的基本原理

    • 自动递增:在一个 const 声明块中,iota 是一个预定义标识符,它在第一行被置为 0,后续每出现一行常量声明,它的值自动加 1。
    • 省略初始化表达式:如果在常量声明块中,后面的常量省略了右侧的表达式,那么它们将默认使用前一行的表达式。这样在简单的复制中,虽然没有太大实用价值,但在配合 iota 时可以生成有规律的值。
  2. 例子

    type Weekday intconst (Sunday Weekday = iota  // 0Monday                 // 1Tuesday                // 2Wednesday              // 3Thursday               // 4Friday                 // 5Saturday               // 6
    )

    这种方式使得常量的赋值变得简单且易于维护。

  3. iota 还常用于生成一系列位掩码(bit mask)

    type Flags uintconst (FlagUp Flags = 1 << iota      // 1 << 0 = 1 (第 0 位)FlagBroadcast                 // 1 << 1 = 2 (第 1 位)FlagLoopback                  // 1 << 2 = 4 (第 2 位)FlagPointToPoint              // 1 << 3 = 8 (第 3 位)FlagMulticast                 // 1 << 4 = 16 (第 4 位)
    )

    每个常量都代表一个单独的 bit 位,这样在设置或测试标志时,可以使用位运算:

    • 测试标志v & FlagUp == FlagUp
    • 清除标志v &^= FlagUp —— 把 v 中与 FlagUp 对应的那一位变成 0(不管原来是1还是0)。这样就清除了这个标志。
    • 设置标志v |= FlagBroadcast —— 把 v 中与 FlagBroadcast 对应的那一位变成1(即使之前是0)
  4. 利用 iota 生成一系列以 1024 为底的幂(例如 KiB、MiB 等)

    const (_ = 1 << (10 * iota)KiB // 1 << 10 = 1024MiB // 1 << 20 = 1048576GiB // 1 << 30 = 1073741824TiB // 1 << 40 = 1099511627776PiB // 1 << 50 = 1125899906842624EiB // 1 << 60 = 1152921504606846976// ZiB, YiB 等可能会超过某些平台的位数限制
    )

    通过这种方式,编译器自动计算出每一项的值,而无需手动写出复杂的计算。

  5. 局限性

    不能产生任意的幂:例如,要生成 1000、1000000 等(通常用于 KB、MB 等),因为 Go 语言没有内置的幂运算符(如 **pow),所以不能直接利用 iota 来生成 10 的幂。

无类型常量的灵活性:隐式转换

当你将无类型常量赋值给一个变量时,Go 编译器会根据上下文自动推断出一个“默认类型”。例如:

  • var x float64 = math.Pi
    这里,math.Pi 是一个无类型浮点常量,赋值时自动转换成 float64。

  • 又如:

    
    i := 0      // 隐式为 int 类型
    f := 0.0    // 隐式为 float64 类型
    c := 0i     // 隐式为 complex128 类型
    r := '\000'// 隐式为 rune(int32)类型

    对于一个没有显式类型的变量声明(包括简短变量声明),常量的形式将隐式决定变量的默认类型,

这种机制让我们在书写表达式时更灵活,无需反复写类型转换代码。

隐式转换与默认类型

当无类型常量出现在需要具体类型的上下文时(比如当一个无类型的常量被赋值给一个变量的时候),编译器会自动进行转换。例如:

var f float64 = 3 + 0i // 这里 3+0i 是无类型复数,但可以隐式转换为 float64

这种转换类似于在后台写了:

var f float64 = float64(3 + 0i)

注意: 转换要求目标类型必须能表示原始常量的值。如果值太大或不适合,则会导致编译错误。例如:

  • 将一个超出 int32 范围的无类型整数转换为 int32,会报错;
  • 将一个超出 float64 表示范围的浮点数转换为 float64,同样会报错。

无类型常量隐式转换的更多例子

var f float64 = 212
fmt.Println((f - 32) * 5 / 9)     // 输出 "100"
fmt.Println(5 / 9 * (f - 32))       // 输出 "0"
fmt.Println(5.0 / 9.0 * (f - 32))   // 输出 "100"
  • 第一行(f - 32) 是 float64,乘以 5 后依然是 float64,然后除以 9,所有运算都是浮点运算,所以结果正确(100)。
  • 第二行5 / 9 两个都是无类型整数(隐式为 int),整数除法结果为 0(因为 5/9 小于 1,用整数运算取整),导致整个表达式结果为 0。
  • 第三行5.09.0 是无类型浮点常量,所以 5.0/9.0 得到正确的浮点值,再乘以 (f - 32) 得到 100。

关键点:常量的写法决定了它们在运算中的默认类型,从而影响最终结果。这也说明了在使用无类型常量时,要注意数值字面量的形式(整数形式或浮点形式)对运算结果的影响。

fmt.Println(YiB / ZiB) // 输出 "1024"
  • 即便 ZiB 和 YiB 的值超出了 Go 内置整数类型能表达的范围,它们仍然可以参与运算.

类型与接口转换

当无类型常量赋值给接口变量时,接口的动态类型取决于常量的默认类型

fmt.Printf("%T\n", 0)      // 输出 "int"
fmt.Printf("%T\n", 0.0)    // 输出 "float64"
fmt.Printf("%T\n", 0i)     // 输出 "complex128"
fmt.Printf("%T\n", '\000') // 输出 "int32"(也称为 rune)

这对接口编程非常关键,因为接口在运行时需要知道底层数据的具体类型。

语言特性

练习

  1. 编写KB、MB的常量声明,然后扩展到YB。

    const (KB = 1000MB = 1000 * KBGB = 1000 * MBTB = 1000 * GBPB = 1000 * TBEB = 1000 * PBZB = 1000 * EBYB = 1000 * ZB
    )

总结

  1. iota 常量生成器:iota 是一个强大的工具,可以方便地生成有规律的数值序列,适用于枚举、位标志、以及其他有序数值集合的定义。
  2. 有一类常量称为“无类型常量”,这类常量在声明时不被赋予一个具体的基础类型,而是保持一种更“通用”的状态。这样做有两个好处:
    • 更高精度的运算:无类型常量在算术运算中拥有比具体类型(如 int 或 float64)更高的精度(可以看作有 256 位或更多位的精度)。
    • 灵活的隐式转换:当无类型常量赋值给变量时,编译器会自动将它们转换成变量所需要的类型(如果转换合法),这样可以直接用于多种场合,减少显式转换的麻烦。

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

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

相关文章

基于x11vnc的ubuntu远程桌面

1、安装VNC服务 sudo apt install x11vnc -y2、创建连接密码 sudo x11vnc -storepasswd3、安装lightdm服务 x11vnc 在 默认的 GDM3 中不起作用&#xff0c;因此需要使用 lightdm 桌面管理环境 sudo apt install lightdm -y切换至lightdm&#xff0c;上一步已经切换则跳过该…

leetcode日记(105)买卖股票的最佳时机Ⅱ

原本以为是一个很难想的动态规划&#xff0c;没想到是最简单的贪心…… 如果实在想不出就画个折线图&#xff0c;只买上涨的就行了&#xff0c;所有上涨的段都取到。 真的没想到会这么简单…… class Solution { public:int maxProfit(vector<int>& prices) {int …

手写发布订阅模式

手写实现一个简易的发布订阅模式&#xff0c;通常有以下几个关键点&#xff1a; 订阅&#xff08;subscribe&#xff09;&#xff1a;用户订阅特定的事件&#xff0c;当该事件触发时&#xff0c;执行与事件关联的回调函数。 发布&#xff08;publish&#xff09;&#xff1a;当…

docker入门篇

使用docker可以很快部署相同的环境,这也是最快的环境构建,接下来就主要对docker中的基础内容进行讲解.Docker 是一个用于开发、交付和运行应用程序的开源平台&#xff0c;它可以让开发者将应用程序及其依赖打包到一个容器中&#xff0c;然后在任何环境中运行这个容器&#xff0…

Qt Widgets、Qt Quick

一、核心概念 ‌Qt Widgets‌ Qt框架中的传统桌面UI开发组件库&#xff0c;基于C实现&#xff0c;提供按钮、文本框等控件‌。适用于需要深度集成操作系统底层功能或复杂业务逻辑的桌面应用‌。 ‌Qt Quick‌ QML的标准库和工具包&#xff0c;提供预置的视觉组件&#xff08;如…

LinuX---Shell正则表达式

正则表达式 正则表达式使用单个字符串来描述、匹配一系列符合某个语法规则的字符串。在很多文本编辑器里&#xff0c;正则表达式通常被用来检索、替换那些符合某个模式的文本。在Linux中&#xff0c;grep&#xff0c;sed&#xff0c;awk等命令都支持通过正则表达式进行模式匹配…

nginx配置txt文件点击链接后下载

手上有一个txt文件&#xff0c;上传到文件服务器后&#xff0c;点击路径是在浏览器里直接打开了&#xff0c;用户需要的是下载到本地 nginx新增配置 location ~* /ExcelDownload/envScript/(.\.txt) {add_header Content-Disposition "attachment; filename$1";add…

相机光学(四十七)——相纸材质

1. 光面相纸 光面相纸表面光滑&#xff0c;亮度高&#xff0c;反光性好&#xff0c;能够呈现出清晰、鲜艳的图像效果&#xff0c;适合用于表现色彩艳丽、反差要求较高的题材&#xff0c;如产品照、艺术照和风景照。然而&#xff0c;这种相纸容易沾上指纹和灰尘。 2. 绒面相纸…

LabVIEW 线性拟合

该 LabVIEW 程序实现了 线性拟合&#xff08;Linear Fit&#xff09;&#xff0c;用于计算给定一组数据点的斜率&#xff08;Slope&#xff09;和截距&#xff08;Intercept&#xff09;&#xff0c;并将结果可视化于 XY Graph 中。本案例适用于数据拟合、实验数据分析、传感器…

Swift 并发中的任务让步(Yielding)和防抖(Debouncing)

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

【Android】RuntimeShader 应用

1 简介 RuntimeShader 是 Android 13&#xff08;T&#xff09;中新增的特性&#xff0c;用于逐像素渲染界面&#xff0c;它使用 AGSL&#xff08;Android Graphics Shading Language&#xff09;编写着色器代码&#xff0c;底层基于 Skia 图形渲染引擎。官方介绍详见 → Runti…

小程序API —— 53 本地存储

小程序本地存储是指在小程序中使用 API 将数据存储在用户的设备上&#xff0c;以便小程序在运行时和下次启动时快速地读取这些数据&#xff1b; 小程序本地存储的 API 可以分为两类&#xff0c;每一类可以分为四种&#xff1a; 同步 API&#xff1a; 存储&#xff1a;wx.setS…

el-table树形表格合并相同的值

el-table树形表格合并相同的值 el-table树形表格合并相同的值让Ai进行优化后的代码 el-table树形表格合并相同的值 <style lang"scss" scoped> .tableBox {/deep/ &.el-table th:first-child,/deep/ &.el-table td:first-child {padding-left: 0;} } …

虚幻基础:移动组件

文章目录 移动组件&#xff1a;角色的移动信息和移动控制walk&#xff1a;行走falling&#xff1a;跳跃&下落 通用设置重力&#xff1a;模式通用重力max acceleration&#xff1a;模式通用加速度 walk制动降速行走&#xff1a;速度超过最大速度时的减速力 falling空气控制空…

DeepSeek + Kimi 自动生成 PPT

可以先用deepseek生成ppt大纲&#xff0c;再把这个大纲复制到Kimi的ppt助手里&#xff1a; https://kimi.moonshot.cn/kimiplus/conpg18t7lagbbsfqksg 选择ppt模板&#xff1a; 点击生成ppt就制作好了。

Unity 解决TMP_Text 文字显示异常的问题

问题 Unity 中TMP_Text 文字显示异常大多可分为两种情况。①制作TMP 字体选用的文本不包含该文字&#xff1b;②制作TMP 字体选用的ttf 源不包含该文字。 第一种情况&#xff0c;制作TMP 字体选用的文本不包含&#xff0c;只需在选用的Charater File 中添加再重新生成即可。 …

Day19:把数字翻译成字符串

现有一串神秘的密文 ciphertext&#xff0c;经调查&#xff0c;密文的特点和规则如下&#xff1a; 密文由非负整数组成数字 0-25 分别对应字母 a-z 请根据上述规则将密文 ciphertext 解密为字母&#xff0c;并返回共有多少种解密结果。 LCR 165. 解密数字 - 力扣&#xff08…

CentOS下安装ElasticSearch(日志分析)

准备目录 搞一个自己喜欢的目录 mkdir /usr/local/app 切换到该目录 cd /usr/local/app 下载 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.9.2-linux-x86_64.tar.gz 选择其他版本 点击进入官网

汽车机械钥匙升级一键启动的优点

汽车机械钥匙升级一键启动的优点主要包括&#xff1a; 便捷性&#xff1a;一键启动功能的引入极大地提升了用车便捷性。车主无需翻找钥匙&#xff0c;只需在车辆感应范围内轻触启动键&#xff0c;即可轻松发动汽车。 安全性&#xff1a;移动管家专车专用一键启动系统配备了防…

【深度学习量化交易16】触发机制设置——基于miniQMT的量化交易回测系统开发实记

我是Mr.看海&#xff0c;我在尝试用信号处理的知识积累和思考方式做量化交易&#xff0c;应用深度学习和AI实现股票自动交易&#xff0c;目的是实现财务自由~ 目前我正在开发基于miniQMT的量化交易系统——看海量化交易系统。 很多朋友关心回测系统的开发进展&#xff0c;在正式…