第4章 - 数据类型
嘿,朋友们!
Go是静态类型语言,了解数据类型很重要。好消息是Go的类型很简洁!我最喜欢的一点是Go的int会根据系统自动选择位数,不用纠结用哪个。当年我学Java的时候,光是记int、long、short就记了好久,还容易记混。
📑 基本数据类型概览
| 类型 | Go | Java | JavaScript |
|---|---|---|---|
| 整数 | int, int8, int32, int64 | int, long | number |
| 浮点 | float32, float64 | float, double | number |
| 字符串 | string | String | string |
| 布尔 | bool | boolean | boolean |
| 字符 | rune (int32) | char | - |
整数类型
有符号整数
var a int8 = 127 // -128 ~ 127
var b int16 = 32767 // -32768 ~ 32767
var c int32 = 2147483647
var d int64 = 9223372036854775807
var e int = 100 // 根据系统自动选择32/64位
无符号整数
var a uint8 = 255 // 0 ~ 255(也叫 byte)
var b uint16 = 65535
var c uint32 = 4294967295
var d uint64 = 18446744073709551615
var e uint = 100
如何选择?
- 一般用
int就够了(最常用) - 需要精确控制内存时用具体类型
- 处理二进制数据用
byte(uint8的别名)
数字字面量
// Go 1.13+ 支持数字分隔符,更易读
bigNumber := 1_000_000_000 // 十亿
// 不同进制
decimal := 42 // 十进制
octal := 0o52 // 八进制 (Go 1.13+)
hex := 0x2A // 十六进制
binary := 0b101010 // 二进制 (Go 1.13+)
浮点类型
var f1 float32 = 3.14
var f2 float64 = 3.141592653589793 // 默认使用float64
// 科学计数法
var f3 = 6.02e23 // 6.02 × 10²³
浮点精度问题
fmt.Println(0.1 + 0.2) // 0.30000000000000004
这是所有语言都有的浮点精度问题,金额计算建议用整数(分为单位)。
字符串
Go的字符串是UTF-8编码的字节序列,不可变。
基本操作
s := "Hello, 世界"
// 长度
fmt.Println(len(s)) // 13(字节数)
fmt.Println(len([]rune(s))) // 9(字符数)
// 拼接
s1 := "Hello" + " " + "World"
s2 := fmt.Sprintf("%s %s", "Hello", "World")
// 索引(获取字节)
fmt.Println(s[0]) // 72 (H的ASCII码)
fmt.Println(string(s[0])) // "H"
// 遍历
for i, c := range s {
fmt.Printf("%d: %c\n", i, c)
}
多行字符串
// 使用反引号(原始字符串)
json := `{
"name": "张三",
"age": 18
}`
// 反引号内的内容原样输出,包括换行
html := `
<html>
<body>Hello</body>
</html>
`
字符串常用操作
import "strings"
s := "Hello, World"
strings.Contains(s, "World") // true - 是否包含
strings.HasPrefix(s, "Hello") // true - 是否以...开头
strings.HasSuffix(s, "World") // true - 是否以...结尾
strings.Index(s, "W") // 7 - 查找位置
strings.ToUpper(s) // "HELLO, WORLD"
strings.ToLower(s) // "hello, world"
strings.TrimSpace(" hi ") // "hi" - 去空格
strings.Split("a,b,c", ",") // ["a", "b", "c"]
strings.Join([]string{"a","b"}, "-") // "a-b"
strings.Replace(s, "World", "Go", 1) // "Hello, Go"
布尔类型
var isActive bool = true
var isDeleted = false
// 逻辑运算
fmt.Println(true && false) // false
fmt.Println(true || false) // true
fmt.Println(!true) // false
// 比较运算结果是布尔值
fmt.Println(1 < 2) // true
fmt.Println("a" == "b") // false
和其他语言的区别
Go的布尔值不能和数字互转!
// Java/JS 可以
if (1) { ... } // 1 当作 true
// Go 不行!
if 1 { } // ❌ 编译错误
if 1 == 1 { } // ✅ 必须是布尔表达式
字符类型 rune
Go用 rune 表示一个Unicode字符(本质是int32)。
var c1 rune = '中'
var c2 rune = 'A'
var c3 = '😀'
fmt.Printf("%c %d\n", c1, c1) // 中 20013
fmt.Printf("%c %d\n", c2, c2) // A 65
fmt.Printf("%c %d\n", c3, c3) // 😀 128512
字符用单引号,字符串用双引号:
char := 'A' // rune类型
str := "A" // string类型
类型转换
Go没有隐式类型转换,必须显式转换:
var i int = 42
var f float64 = float64(i) // int → float64
var u uint = uint(f) // float64 → uint
// 数字和字符串转换
import "strconv"
// 字符串 → 数字
num, _ := strconv.Atoi("42") // string → int
f, _ := strconv.ParseFloat("3.14", 64) // string → float64
// 数字 → 字符串
str := strconv.Itoa(42) // int → string
str2 := strconv.FormatFloat(3.14, 'f', 2, 64) // float → string
str3 := fmt.Sprintf("%d", 42) // 万能方法
对比Java
// Java可以隐式转换
int i = 42;
double d = i; // 自动转换
// Go必须显式
i := 42
d := float64(i) // 必须手动转
Go更严格,但也更安全,不会有意外的类型转换。
类型别名
// 自定义类型
type Age int
type Money float64
var age Age = 25
var price Money = 9.99
// 类型别名(Go 1.9+)
type Byte = uint8 // byte是uint8的别名
type Rune = int32 // rune是int32的别名
类型推断查看
package main
import "fmt"
func main() {
a := 42
b := 3.14
c := "hello"
d := true
e := 'A'
// 使用 %T 打印类型
fmt.Printf("a: %T = %v\n", a, a) // int
fmt.Printf("b: %T = %v\n", b, b) // float64
fmt.Printf("c: %T = %v\n", c, c) // string
fmt.Printf("d: %T = %v\n", d, d) // bool
fmt.Printf("e: %T = %v\n", e, e) // int32 (rune)
}
实战案例:学生成绩管理
package main
import (
"fmt"
"strings"
)
func main() {
// 学生信息
name := "张三"
studentID := int64(2024001)
score := 85.5
isPassed := score >= 60
grade := 'B'
// 格式化输出
fmt.Println(strings.Repeat("=", 30))
fmt.Printf("姓名: %s\n", name)
fmt.Printf("学号: %d\n", studentID)
fmt.Printf("成绩: %.1f\n", score)
fmt.Printf("是否及格: %t\n", isPassed)
fmt.Printf("等级: %c\n", grade)
fmt.Println(strings.Repeat("=", 30))
// 类型转换演示
scoreInt := int(score) // 转整数(截断小数)
fmt.Printf("成绩取整: %d\n", scoreInt)
// 字符串拼接
info := fmt.Sprintf("学生%s的成绩是%.1f分", name, score)
fmt.Println(info)
}
输出:
==============================
姓名: 张三
学号: 2024001
成绩: 85.5
是否及格: true
等级: B
==============================
成绩取整: 85
学生张三的成绩是85.5分
练习
- 声明不同类型的变量,使用
%T打印它们的类型 - 将字符串 "123" 转换为数字并加10
- 统计字符串 "Hello, 世界" 的字节数和字符数
参考答案
package main
import (
"fmt"
"strconv"
)
func main() {
// 1. 打印类型
var i int = 10
var f float64 = 3.14
var s string = "hello"
var b bool = true
fmt.Printf("int: %T\n", i)
fmt.Printf("float64: %T\n", f)
fmt.Printf("string: %T\n", s)
fmt.Printf("bool: %T\n", b)
// 2. 字符串转数字
numStr := "123"
num, _ := strconv.Atoi(numStr)
result := num + 10
fmt.Printf("%s + 10 = %d\n", numStr, result)
// 3. 统计长度
str := "Hello, 世界"
byteLen := len(str)
runeLen := len([]rune(str))
fmt.Printf("字符串: %s\n", str)
fmt.Printf("字节数: %d\n", byteLen)
fmt.Printf("字符数: %d\n", runeLen)
}
了解了数据类型,下一节我们学习控制流程!
