基础语法(上):变量声明、常量与iota、基本数据类型、类型转换
说实话,每次带新人入门Go语言,我都是从变量声明开始讲起的。为什么?因为Go在这块的设计,跟Java、Python都不太一样。你上手写几行代码就能感受到——这语言是真的「简洁」。
好,咱们直接开干。
1. 变量声明:var 与 :=
Go语言里声明变量,主要有两种方式。我个人的习惯是:能用短声明就用短声明,除非有特殊需求。
1.1 使用 var 关键字
这是最传统的写法,跟C语言有点像,但类型写在变量名后面。
var name string = "张三"
var age int = 25
var isStudent bool = true
你也可以省略类型,让编译器自己推断:
var name = "张三" // 自动推断为 string
var age = 25 // 自动推断为 int
嗯,这里要注意:如果你只声明不赋值,必须带上类型。否则编译器会懵——「你让我猜类型,又不给我值,我怎么猜?」
var name string // 正确,name 默认值为 ""
var age // 编译错误:no new variables on left side of :=
1.2 使用 := 短变量声明
这是Go最让我舒服的特性之一。在函数内部,你可以直接用 := 来声明并初始化变量:
name := "张三"
age := 25
isStudent := true
你看,代码是不是清爽多了?我在项目中写业务逻辑时,几乎90%的场景都用 :=。但有个坑——短声明只能在函数内部使用。包级别的变量,还是得老老实实用 var。
name := "张三",编译直接报错。当时我还纳闷:「这语法不是挺常见的吗?」后来才意识到——短声明是函数内专用的。
1.3 多变量声明
Go支持一次声明多个变量,这在处理函数返回值时特别有用:
var x, y int = 1, 2
a, b := "hello", true
我个人觉得,这种写法在解构赋值时特别优雅。比如调用一个返回多个值的函数:
result, err := doSomething()
你想想看,如果每个返回值都要单独声明,那代码得多啰嗦。
2. 常量与 iota
常量在Go里用 const 关键字声明。跟变量不同,常量一旦定义就不能修改。这个大家都懂,我就不多说了。
2.1 普通常量
const Pi = 3.14159
const MaxRetries = 3
常量也可以分组声明:
const (
StatusOK = 200
StatusNotFound = 404
StatusServerError = 500
)
2.2 iota:Go的枚举神器
这个 iota 是我觉得Go里最巧妙的设计之一。它是个常量生成器,在 const 块里每出现一次,值就自动加1。
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
Wednesday // 3
Thursday // 4
Friday // 5
Saturday // 6
)
说白了,iota 就是帮你省去手动编号的麻烦。我在项目中定义日志级别时经常用:
const (
LevelDebug = iota
LevelInfo
LevelWarn
LevelError
)
你还可以玩点花样,比如跳过某些值:
const (
_ = iota // 0,被忽略
KB = 1 << (10 * iota) // 1 << 10 = 1024
MB // 1 << 20 = 1048576
GB // 1 << 30 = 1073741824
)
First = iota + 1。这样第一个值就是1,而不是0。
3. 基本数据类型
Go是强类型语言,每个变量都有明确的类型。常用的基本类型就这几种:
| 类型 | 说明 | 默认值 |
|---|---|---|
| int | 整数,根据平台可能是32位或64位 | 0 |
| float64 | 浮点数,常用这个 | 0.0 |
| string | 字符串,不可变 | "" |
| bool | 布尔值 | false |
3.1 int 类型
Go的整数类型分得很细:int8、int16、int32、int64,还有无符号的 uint 系列。但日常开发中,我基本只用 int。为什么?因为够用,而且不用操心位数问题。
var a int = 42
var b int64 = 42 // 这是不同的类型!
嗯,这里有个坑:int 和 int64 不是同一个类型。你不能直接把 int 赋值给 int64,必须做类型转换。我刚开始学Go时就被这个坑过。
3.2 float 类型
浮点数有 float32 和 float64。我建议你直接用 float64,精度更高,而且很多标准库函数都默认用这个。
var price float64 = 19.99
var tax float32 = 0.08 // 精度较低,不推荐
3.3 string 类型
字符串在Go里是UTF-8编码的,支持各种语言字符。你可以用双引号或反引号:
s1 := "Hello, 世界"
s2 := `多行
字符串
直接写`
反引号的好处是:里面的内容原样输出,不需要转义。我在写SQL语句或JSON模板时特别喜欢用。
3.4 bool 类型
布尔值只有 true 和 false。注意,Go里不能把整数当布尔用——这是跟C语言最大的区别。
var flag bool = true
if flag { // 正确
fmt.Println("true")
}
// if 1 { // 编译错误!1 不能当作布尔值
// fmt.Println("true")
// }
4. 类型转换
Go是强类型语言,类型转换必须显式进行。你不能像Python那样随意混用类型。
4.1 基本语法
类型转换的写法是 T(v),把值 v 转换为类型 T:
var a int = 42
var b float64 = float64(a) // int → float64
var c int = int(b) // float64 → int,小数部分被截断
我曾经在项目中遇到过一个问题:把一个 float64 转成 int 时,小数部分直接丢了,导致计算结果偏差。后来我改用 math.Round 先四舍五入再转换。
4.2 字符串与数字的转换
这个稍微麻烦点,需要借助 strconv 包:
import "strconv"
// 字符串转整数
s := "42"
n, err := strconv.Atoi(s)
if err != nil {
// 处理错误
}
// 整数转字符串
s2 := strconv.Itoa(42)
// 字符串转浮点数
f, err := strconv.ParseFloat("3.14", 64)
string 直接转成 int,也不能把 bool 转成 int。Go在这块非常严格——我觉得这是好事,能避免很多隐晦的bug。
4.3 类型断言(接口相关)
这个稍微进阶一点,但我觉得有必要提一下。当你有一个接口类型的值时,可以用类型断言来获取其具体类型:
var i interface{} = "hello"
s, ok := i.(string)
if ok {
fmt.Println(s) // 输出 "hello"
}
你想想看,如果没有类型断言,你怎么知道接口里装的是什么类型?
5. 避坑指南
最后,我总结几个新手容易踩的坑:
- 变量声明后必须使用:Go编译器会报错,这是Go的设计哲学——「没用的代码就是垃圾」。
- 短声明不能用于全局:包级别变量只能用
var。 - 类型转换必须显式:别指望Go帮你自动转,它不会。
- iota 从0开始:如果你需要从1开始,记得加1。
好了,这一章的内容就到这里。下一章我们会深入控制流——if、for、switch这些。到时候我会分享一些我在实际项目中用到的骚操作,敬请期待。