☰
90DaysOfDevOps 之 Go 语言变量与常量入门(Day 11)
2026/9/30 2:16:43 网站建设 项目流程
  • 文档/教程

【免费下载链接】90DaysOfDevOps

This repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things DevOps, including Principles, Processes, Tooling and Use Cases surrounding this vast topic.

项目地址:https://gitcode.com/gh_mirrors/90/90DaysOfDevOps
点击查看免费下载

本文基于 90DaysOfDevOps 开源仓库第 11 天的学习笔记,系统讲解 Go 语言中变量(Variables)、常量(Constants)与数据类型(Data Types)的核心概念,并围绕“统计 #90DaysOfDevOps 挑战已坚持天数”这一真实小应用,逐步演示从声明变量、引入常量到格式化输出的完整编码流程。读完本文,你将掌握 Go 变量的三种声明方式、常量与变量的区别、四大数据类型分类,以及Println/Printf输出与%T类型打印等实战技巧。

从第 8~10 天延续下来的 Go 学习路线

在进入今天的主题之前,先回顾一下这条学习路线:第 8 天(Day 8)完成了 Go 开发环境的搭建;第 9 天(Day 9)逐行拆解了 Hello #90DaysOfDevOps 程序;第 10 天(Day 10)深入介绍了 Go 的工作区以及编译与运行代码的流程。今天是第 11 天,我们将在此基础上正式接触编程语言的核心构件——变量、常量与数据类型,并动手编写一个新程序。

为什么要用变量:一次定义,处处复用

在编写一个“统计挑战进度”的程序时,我们会多次向参与者输出 #90DaysOfDevOps 这个挑战名称。与其在每行代码里重复硬编码这一长串文本,不如把它保存到一个变量里。变量在 Go 中的作用可以概括为三点:

  • 变量用于存储值,它就像一个小盒子,保存着我们需要的信息或数值;
  • 变量可以在整个程序中复用,当挑战名称这类值发生变化时,只需修改一处声明,程序里所有引用它的地方都会同步更新;
  • 借助这一特性,同一套代码稍作改动就能复用到社区的其他挑战项目上——只需改变这一个变量的值即可。

在 Go 程序中,声明变量需要使用关键字var。下面的代码将挑战名称存入变量challenge,这一行会放在func main代码块内:

var challenge = "#90DaysOfDevOps"

这里有两个值得注意的编码规范:

  1. 变量命名要有描述性——challenge比c更能表达含义;
  2. 声明了变量就必须使用它,否则编译器会报错(unused variable),这是 Go 为避免“死代码”(永远不会执行的代码)而采取的强制措施;未使用的包(package)同理也会报错。

将变量代入完整的程序中,即可输出欢迎语,完整代码见 day11_example1.go:

package main import "fmt" func main() { var challenge = "#90DaysOfDevOps" fmt.Println("Welcome to", challenge, "") }

运行结果如下图所示:

常量(const):运行期不可变的固定值

我们已经知道挑战名义上是 90 天,但未来它可能变成 100 天或其他数值。对这个“挑战总天数”,我们希望它固定不变——这正是引入常量(constant)的场景。

常量和变量类似,但区别在于:常量在代码运行期间的值不可被修改。当然,未来我们在新的应用中复用这份代码时,仍然可以修改这个常量声明本身;但在当前程序运行过程中,这个 90 不会发生任何变化。

在第 2 版程序中,我们加入const daystotal = 90并用一行新的Println输出它,完整代码见 day11_example2.go:

package main import "fmt" func main() { var challenge = "#90DaysOfDevOps" const daystotal = 90 fmt.Println("Welcome to", challenge, "") fmt.Println("This is a", daystotal, "challenge") }

再次执行go build并运行(或直接用go run),输出结果如下:

加入动态变量:记录已完成的天数

程序还没写完——第 12 天会为它增加更多功能。现在我们再添加一个记录“已完成天数”的变量dayscomplete,并通过fmt.Println把它拼进输出消息,完整代码见 day11_example3.go:

package main import "fmt" func main() { var challenge = "#90DaysOfDevOps" const daystotal = 90 var dayscomplete = 11 fmt.Println("Welcome to", challenge, "") fmt.Println("This is a", daystotal, "challenge and you have completed", dayscomplete, "days") fmt.Println("Great work") }

执行结果如下:

到这里,程序已经能够完整展示“挑战名称、总天数、已完成天数”三个信息。下一步(Day 12)将引入用户输入功能,让程序询问用户已完成多少天——届时硬编码的dayscomplete会被fmt.Scan读取的用户输入取代。

用 Printf 与 %v 让输出更简洁

前面的例子一直使用fmt.Println,每个变量都要作为参数逐个传入。为了让代码更易读、更易维护,Go 的fmt包还提供了Printf格式化输出:

  • %v表示使用变量的默认值格式输出,多个变量按顺序放在行末的参数位置;
  • \n表示换行(line break);
  • 除了%v,fmt包还提供了%T(类型)、%d(十进制整数)、%s(字符串)等大量格式动词,完整清单可查阅 Go 标准库fmt包文档。

使用Printf改写后的代码见 day11_example4.go:

package main import "fmt" func main() { var challenge = "#90DaysOfDevOps" const daystotal = 90 var dayscomplete = 11 fmt.Printf("Welcome to %v\n", challenge) fmt.Printf("This is a %v challenge and you have completed %v days\n", daystotal, dayscomplete) fmt.Println("Great work") }

更简洁的声明语法:短变量声明:=

除了var关键字,Go 还提供了一种更简洁的变量声明方式:使用:=,由编译器根据右侧赋值自动推断类型。这样写出来的代码更干净、更简洁:

func main() { challenge := "#90DaysOfDevOps" const daystotal = 90

重要限制::=只适用于变量,不适用于常量。常量仍然必须使用const关键字声明。另外,:=只能在函数内部使用;在函数外(如包级别)声明变量仍需使用var。

数据类型(Data Types)

在前面的代码中,我们并没有显式指定变量的类型——因为 Go 足够“聪明”,可以根据赋值自动推断类型:"#90DaysOfDevOps"是字符串(string),90、11是整数(int)。但如果变量需要接受用户输入,就必须明确指定类型。

不同数据类型的行为也不同:例如整数可以相乘,而字符串不能。因此,理解数据类型是编程的重要基础——数据类型决定了变量值的存储大小和类型。

Go 的类型可以归纳为四大类别:

  • 基本类型(Basic type):数字(Numbers)、字符串(Strings)、布尔值(Booleans)属于此类;
  • 聚合类型(Aggregate type):数组(Array)和结构体(Structs)属于此类;
  • 引用类型(Reference type):指针(Pointers)、切片(Slices)、映射(Maps)、函数(Functions)、通道(Channels)属于此类;
  • 接口类型(Interface type)。

Go 是一门静态类型语言(statically typed):一旦变量类型被定义,它就只能存储该类型的数据。Go 有三种基本数据类型:

  • bool:布尔值,取值为true或false;
  • Numeric(数值类型):包括整数类型、浮点数值和复数类型;
  • string:字符串值。

如果需要在声明时显式指定类型,可以这样写:

var TwitterHandle string var DaysCompleted uint

在这里,TwitterHandle被指定为string类型,DaysCompleted被指定为uint(无符号整数)类型。对数值类型做一个简单归纳:

  • int= 整数(whole numbers),可正可负;
  • uint= 非负整数(positive whole numbers);
  • 浮点类型(floating point types)= 包含小数部分的数字。

用 %T 打印变量类型

因为 Go 会根据赋值自动推断类型,我们可以在运行时用Printf配合%T格式动词打印出每个变量实际推断出的类型,这是排查类型问题最直接的手段:

fmt.Printf("challenge is %T, daystotal is %T, dayscomplete is %T\n", conference, daystotal, dayscomplete)

从仓库源码看 Go 学习的配套工程实践

在本仓库的 2022/Days/Go 目录下,除了今天这 4 个示例文件(day11_example1.go到day11_example4.go),还存放着后续第 12、13 天的示例(day12_example1.go~day13_example3.go)以及最初的 hello.go。目录中的 makefile 展示了跨平台编译的典型用法——通过GOOS/GOARCH环境变量,一条make build命令即可为 darwin/linux/windows 以及 amd64/arm64 架构分别产出二进制文件:

BINARY_NAME=90DaysOfDevOps build: GOARCH=amd64 GOOS=darwin go build -o ${BINARY_NAME}_0.2_darwin main.go GOARCH=amd64 GOOS=linux go build -o ${BINARY_NAME}_0.2_linux main.go GOARCH=amd64 GOOS=windows go build -o ${BINARY_NAME}_0.2_windows main.go GOARCH=arm64 GOOS=linux go build -o ${BINARY_NAME}_0.2_linux_arm64 main.go GOARCH=arm64 GOOS=darwin go build -o ${BINARY_NAME}_0.2_darwin_arm64 main.go

也就是说,今天学习的变量与常量会自然地应用到后续的完整程序中——第 12 天(Day 12)的示例代码就是在day11_example4.go的基础上,新增TwitterName、DaysCompleted变量并借助fmt.Scan(&TwitterName)读取用户输入,同时引入指针(&)概念完成剩余天数的计算。把第 11 天的变量、常量与数据类型基础打牢,是理解后续指针、用户输入乃至完整程序的关键一步。

小结

今天围绕“统计 #90DaysOfDevOps 挑战天数”的小程序,掌握了以下 Go 核心知识:

  • 变量:用var声明、存储可复用的值;命名要描述性强,声明必用;
  • 常量:用const声明,运行期内值不可变,适合表示挑战总天数这类固定值;
  • 短变量声明::=语法更简洁,但仅限变量且只能在函数内部使用;
  • 输出:Println逐参数拼接 vsPrintf+%v/%T格式化,\n换行;
  • 类型系统:Go 是静态类型语言,类型分为基本、聚合、引用、接口四大类,其中基本类型为 bool、Numeric、string;整数分int(可正可负)与uint(非负),浮点类型用于小数。

下一步,我们将为程序加入用户输入功能,让程序主动询问“已完成多少天”——See you on Day 12。

  • 文档/教程

【免费下载链接】90DaysOfDevOps

This repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things DevOps, including Principles, Processes, Tooling and Use Cases surrounding this vast topic.

项目地址:https://gitcode.com/gh_mirrors/90/90DaysOfDevOps
点击查看免费下载
上一篇:鸣潮工具箱WaveTools:3步解决抽卡数据同步问题,轻松管理你的游戏体验
下一篇:Readest TTS 与段落模式、速读器同步设计:基于 CFI 的「跟随音频」机制全解析

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询