概述
Go语言以其简洁的类型系统著称,变量声明方式多样,数据类型清晰明了。本文详细介绍Go语言中的变量声明、基本数据类型、类型转换以及可见性规则,帮助读者打下坚实的类型基础。
一、变量声明
1.1 var 声明
标准的变量声明使用 var 关键字:
Go
// 基本语法
var name string = "张三"
var age int = 25
var isStudent bool = true
// 类型推断(省略类型)
var name = "张三" // 推断为 string
var age = 25 // 推断为 int
var isStudent = true // 推断为 bool
// 声明多个变量
var (
name string
age int
city string = "北京"
)
1.2 短变量声明(:=)
在函数内部,可以使用 := 进行短变量声明:
Go
func main() {
name := "Go语言" // 等价于 var name string = "Go语言"
version := 1.22 // 等价于 var version int = 1.22
price := 99.9 // 等价于 var price float64 = 99.9
fmt.Println(name, version, price)
}
重要规则:
-
:=只能在函数内部使用,不能用于全局变量声明 -
左侧至少有一个变量是新建的,不能全是已存在的变量
// 正确示例
a, b := 1, 2 // 两个都是新建
a, c := 1, 3 // a已存在,c新建
// 错误示例
a, b := 1, 2 // 错误:没有新变量
1.3 常量声明
常量使用 const 关键字,值在编译时确定:
Go
const Pi float64 = 3.14159
const AppName = "MyApp" // 类型推断
const (
StatusOK = 200
StatusNotFound = 404
StatusError = 500
)
// iota:常量计数器,用于生成枚举值
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
Wednesday // 3
Thursday // 4
Friday // 5
Saturday // 6
)
1.4 零值机制
Go语言中,未初始化的变量会自动赋零值:
| 类型 | 零值 |
|---|---|
| 数值类型(int, float) | 0 |
| 布尔类型 bool | false |
| 字符串 string | ""(空字符串) |
| 指针、切片、map、channel、interface | nil |
Go
func main() {
var i int
var f float64
var b bool
var s string
var arr []int
fmt.Printf("int零值: %d\n", i)
fmt.Printf("float零值: %f\n", f)
fmt.Printf("bool零值: %t\n", b)
fmt.Printf("string零值: '%s'\n", s)
fmt.Printf("slice零值: %v (nil: %t)\n", arr, arr == nil)
}
输出:
int零值: 0
float零值: 0.000000
bool零值: false
string零值: ''
slice零值: [] (nil: true)
二、基本数据类型
2.1 整数类型
Go的整数类型分为有符号和无符号两大类:
有符号整数:
| 类型 | 描述 | 范围 |
|---|---|---|
| int8 | 8位有符号 | -128 ~ 127 |
| int16 | 16位有符号 | -32768 ~ 32767 |
| int32 | 32位有符号 | -2147483648 ~ 2147483647 |
| int64 | 64位有符号 | -9223372036854775808 ~ 9223372036854775807 |
| int | 平台相关(32/64位) | 取决于平台 |
无符号整数:
| 类型 | 描述 | 范围 |
|---|---|---|
| uint8 | 8位无符号 | 0 ~ 255 |
| uint16 | 16位无符号 | 0 ~ 65535 |
| uint32 | 32位无符号 | 0 ~ 4294967295 |
| uint64 | 64位无符号 | 0 ~ 18446744073709551615 |
| uint | 平台相关 | 取决于平台 |
| byte | uint8 的别名 | 0 ~ 255 |
| rune | int32 的别名(Unicode码点) | -2147483648 ~ 2147483647 |
Go
func main() {
// 有符号整数
var a int8 = 127
var b int16 = -128
var c int32 = 2147483647
var d int64 = -9223372036854775808
// 无符号整数
var e uint8 = 255
var f uint16 = 65535
// byte 和 rune
var g byte = 65 // ASCII 'A'
var h rune = '中' // Unicode码点
fmt.Printf("int8: %d\n", a)
fmt.Printf("int16: %d\n", b)
fmt.Printf("byte: %c (ASCII 65)\n", g)
fmt.Printf("rune: %c (Unicode)\n", h)
}
2.2 浮点数类型
| 类型 | 描述 | 精度 |
|---|---|---|
| float32 | 32位浮点数 | 约7位十进制数字 |
| float64 | 64位浮点数 | 约15位十进制数字(推荐使用) |
Go
func main() {
var a float32 = 3.1415926
var b float64 = 3.141592653589793
fmt.Printf("float32: %f\n", a)
fmt.Printf("float32: %.6f\n", a)
fmt.Printf("float64: %.15f\n", b)
// 科学计数法
fmt.Printf("float64科学计数: %e\n", b)
// 特殊值
fmt.Printf("无穷大: %f\n", math.Inf(1))
fmt.Printf("负无穷: %f\n", math.Inf(-1))
fmt.Printf("NaN: %f\n", math.NaN())
}
2.3 复数类型
Go支持复数运算:
Go
func main() {
var c1 complex64 = 1 + 2i
var c2 complex128 = 3 + 4i
fmt.Printf("c1: %v\n", c1)
fmt.Printf("c2: %v\n", c2)
fmt.Printf("c1 + c2 = %v\n", c1 + c2)
fmt.Printf("c1 * c2 = %v\n", c1 * c2)
fmt.Printf("real(c1) = %f, imag(c1) = %f\n", real(c1), imag(c1))
}
2.4 字符串类型
Go字符串是UTF-8编码的不可变字节序列:
Go
func main() {
s1 := "Hello, Go!"
s2 := "你好,Go语言!"
fmt.Println(s1)
fmt.Println(s2)
// 字符串长度(字节数)
fmt.Printf("s1字节长度: %d\n", len(s1))
fmt.Printf("s2字节长度: %d\n", len(s2))
// 字符个数(rune数)
fmt.Printf("s2字符个数: %d\n", len([]rune(s2)))
// 访问单个字节
fmt.Printf("s1[0] = %c (字节值: %d)\n", s1[0], s1[0])
}
2.5 布尔类型
布尔类型只有两个值:true 和 false:
Go
func main() {
var a bool = true
var b bool = false
// 短路求值
c := a && b // false(a为true,但b为false)
d := a || b // true(a为true,无需计算b)
fmt.Printf("a && b = %t\n", c)
fmt.Printf("a || b = %t\n", d)
fmt.Printf("!a = %t\n", !a)
}
三、类型转换
Go语言没有隐式类型转换,必须显式转换:
3.1 数值类型转换
Go
func main() {
// int 转 float
var i int = 42
var f float64 = float64(i)
fmt.Printf("int->float64: %f\n", f)
// float 转 int(丢失小数部分)
var f2 float64 = 3.99
var i2 int = int(f2)
fmt.Printf("float64->int: %d (截断)\n", i2)
// int8, int16, int32, int64 互转
var i64 int64 = 1000
var i32 int32 = int32(i64)
var i16 int16 = int16(i32)
var i8 int8 = int8(i16)
fmt.Printf("int64->int8: %d\n", i8)
}
⚠️ 溢出问题:
Go
func main() {
var i int8 = 127
var i2 int8 = int8(i + 1) // 溢出,结果为-128
fmt.Printf("int8溢出: %d\n", i2)
var u uint8 = 255
var u2 uint8 = u + 1 // 溢出,结果为0
fmt.Printf("uint8溢出: %d\n", u2)
}
3.2 字符串与字节切片互转
Go
func main() {
// string 转 []byte
s := "Hello"
b := []byte(s)
fmt.Printf("[]byte: %v\n", b)
// []byte 转 string
b2 := []byte{72, 101, 108, 108, 111}
s2 := string(b2)
fmt.Printf("string: %s\n", s2)
// string 转 []rune(处理中文)
s3 := "你好"
r := []rune(s3)
fmt.Printf("[]rune: %v (Unicode码点)\n", r)
fmt.Printf("字符个数: %d\n", len(r))
// []rune 转 string
r2 := []rune{0x4E2D, 0x6587}
s4 := string(r2)
fmt.Printf("string: %s\n", s4)
}
3.3 strconv 包转换
Go
import "strconv"
func main() {
// 字符串转数值
i, _ := strconv.Atoi("42")
fmt.Printf("Atoi: %d\n", i)
f, _ := strconv.ParseFloat("3.14", 64)
fmt.Printf("ParseFloat: %.2f\n", f)
b, _ := strconv.ParseBool("true")
fmt.Printf("ParseBool: %t\n", b)
// 数值转字符串
s1 := strconv.Itoa(42)
s2 := strconv.FormatFloat(3.14, 'f', 2, 64)
s3 := strconv.FormatBool(true)
fmt.Printf("Itoa: %s\n", s1)
fmt.Printf("FormatFloat: %s\n", s2)
fmt.Printf("FormatBool: %s\n", s3)
}
四、可见性规则
Go语言使用首字母大小写来控制标识符的可见性:
Go
package mypackage
import "fmt"
// MyPublicFunc 首字母大写,可被其他包导出
func MyPublicFunc() {
fmt.Println("我是公开函数")
}
// myPrivateFunc 首字母小写,仅限本包内使用
func myPrivateFunc() {
fmt.Println("我是私有函数")
}
// MyPublicVar 公开变量
var MyPublicVar = 100
// myPrivateVar 私有变量
var myPrivateVar = 200
// MyPublicType 公开结构体
type MyPublicType struct {
Name string // 公开字段
age int // 私有字段
}
规则总结:
-
首字母大写:导出标识符,可被其他包访问
-
首字母小写:未导出标识符,仅限本包内访问
五、命名规范
5.1 变量命名
Go语言推崇简洁、有意义的命名:
Go
// ✅ 推荐:简洁清晰
userName := "张三"
isActive := true
itemCount := 0
// ❌ 避免:过于简短或无意义
x := "张三" // x是什么?
a := 1 // a是什么?
data := "" // 什么数据?
// ❌ 避免:中文拼音
xingming := "张三"
5.2 常量命名
Go
// 常量组命名规范
const (
StatusOK = 200
StatusNotFound = 404
StatusError = 500
)
// 枚举类型通常使用 iota
const (
Monday = iota
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
)
5.3 包命名
Go
// ✅ 推荐:简短、全小写、不含下划线
import (
"fmt"
"strings"
"os/user"
)
// ❌ 避免:下划线、混合大小写
// import "my_package" // 下划线不推荐
// import "MyPackage" // 混合大小写不推荐
六、代码规范检查
使用 go vet 和 gofmt 保持代码规范:
Go
# 格式化代码
go fmt ./...
# 检查代码问题
go vet ./...
# 使用 golangci-lint(需安装)
golangci-lint run
总结
本文详细介绍了Go语言的变量声明、数据类型、类型转换和可见性规则。需要牢记:
-
变量声明 :
var声明可带类型,:=用于函数内短声明 -
数据类型:数值、字符串、布尔、rune/byte
-
类型转换:必须显式转换,不存在隐式转换
-
可见性:首字母大写为导出,小写为私有
思考题:
-
var a int = 3.14为什么不能编译通过? -
如何正确判断中文字符串的长度?
-
为什么推荐使用 float64 而不是 float32?
📚 下一篇文章我们将深入讲解 Go 语言的运算符与控制流程,敬请期待!