语法基础对比速览
本章快速对比Python与Go语法:变量声明、类型系统、数据类型、控制流、函数。重点:Go静态类型+零值机制 vs Python动态类型,理解两者核心差异。
前置知识:Python基础语法 学习目标:能读懂Go代码、理解Go类型系统、掌握语法对应关系
3.1 变量声明与类型系统
Section titled “3.1 变量声明与类型系统”Python变量机制
Section titled “Python变量机制”Python是动态类型,变量是引用:
# Python - 变量是标签x = 10 # 创建int对象10,x指向它y = x # y也指向同一个int对象10x = 20 # x指向新的int对象20,y仍指向10
print(x) # 20print(y) # 10
# 类型随时变化x = "hello"print(x) # hello变量本身无类型,类型属于对象。
Go变量机制
Section titled “Go变量机制”Go是静态类型,变量有类型:
// Go - 变量是容器var x int = 10 // x是int类型容器,值为10var y int = x // y是新的int容器,值为20的副本x = 20 // x的值变为20,y不变
fmt.Println(x) // 20fmt.Println(y) // 10
// 类型固定,不可改变// x = "hello" // 编译错误:无法将string赋值给intGo变量声明方式
Section titled “Go变量声明方式”方式一:var + 类型 + 初始值
var age int = 25var name string = "Alice"var isStudent bool = true方式二:var + 类型(零值初始化)
var age int // 0var name string // ""var isStudent bool // false
// 常用:声明后赋值var age intage = 25方式三:短变量声明(函数内)
func main() { // 最常用方式 name := "Alice" // 推导为string age := 25 // 推导为int isStudent := true // 推导为bool
// 多变量 x, y := 1, 2
fmt.Println(name, age, isStudent) // Alice 25 true}方式四:var()批量声明
var ( name string = "Alice" age int = 25 city string = "Beijing")Python vs Go对比
Section titled “Python vs Go对比”| Python | Go | 说明 |
|---|---|---|
x = 10 | var x int = 10 | 显式类型 |
x = 10 | x := 10 | 类型推导 |
x, y = 1, 2 | x, y := 1, 2 | 多赋值 |
x = y = 10 | var x, y int = 10, 10 | 链式赋值 |
| 无法声明无初始值 | var x int | Go零值机制 |
零值机制(Zero Value)
Section titled “零值机制(Zero Value)”Go的变量总有默认值:
var i int // 0var f float64 // 0.0var b bool // falsevar s string // ""
var ptr *int // nil(指针)var slice []int // nilvar m map[string]int // nilPython无此机制,未初始化的变量会报错。
Go有指针,Python无:
// &取地址,*解引用x := 10p := &x // p是指向x的指针,类型*intfmt.Println(p) // 打印地址,如0xc0000a6000fmt.Println(*p) // 10,解引用获取值
*p = 20 // 通过指针修改xfmt.Println(x) // 20Python无法获取变量地址,但可以用id()模拟:
x = 10print(id(x)) # 类似地址# Python不暴露指针机制3.2 数据类型一览
Section titled “3.2 数据类型一览”本节目的:对比Python/Go数据类型、理解Go固定宽度整数的优缺点
Go整数类型(固定宽度):
| 类型 | 有符号 | 范围 | Python对应 |
|---|---|---|---|
| int8 | 是 | -128~127 | - |
| int16 | 是 | -32768~32767 | - |
| int32 | 是 | -21亿~21亿 | int |
| int64 | 是 | 很大 | int |
| uint8 | 否 | 0~255 | - |
| uint16 | 否 | 0~65535 | - |
| uint32 | 否 | 0~42亿 | - |
| uint64 | 否 | 很大 | - |
常用简写:
int // 平台相关(32或64位)uint // 平台相关uintptr // 足够大以保存指针与Python的差异:
- Python int是任意精度,Go int是固定精度
- Go对溢出严格处理,Python自动扩展
var i int32 = 2147483647i += 1 // 溢出:变成-2147483648i = 2147483647i += 1 # Python自动扩展:2147483648字面量:
a := 100 // 十进制b := 0xFF // 十六进制 (255)c := 0o777 // 八进制 (511)d := 0b1010 // 二进制 (10)
// 下划线分隔(Go 1.13+)big := 1_000_000 // 1000000hex := 0xFFFF_FFFF // 4294967295| 类型 | 精度 | Python对应 |
|---|---|---|
| float32 | 6-7位十进制精度 | float |
| float64 | 15-17位精度 | float |
var f1 float64 = 3.141592653589793var f2 float32 = 3.14159
fmt.Printf("%.10f\n", f1) // 3.1415926536fmt.Printf("%.7f\n", f2) // 3.1415900特殊值:
inf := math.Inf(1) // 正无穷ninf := math.Inf(-1) // 负无穷nan := math.NaN() // 非数
// NaN比较(特殊规则)math.NaN() == math.NaN() // falsemath.IsNaN(nan) // truevar b1 bool = truevar b2 bool = false
// 短声明active := truedeleted := false
// 布尔运算and := true && false // falseor := true || false // truenot := !true // falsePython对应:True, False, and, or, not
var s1 string = "Hello"var s2 string = "世界"
// 字符串是UTF-8编码的字节序列s3 := "Hello, 世界"
fmt.Println(len(s3)) // 13(字节数)fmt.Println(utf8.RuneCountInString(s3)) // 9(字符数)Python对应:str类型,Unicode原生支持。
字符串不可变:
s := "hello"// s[0] = 'H' // 编译错误:无法修改字符串
// 必须创建新字符串s2 := "H" + s[1:] // "Hello"Python字符串也不可变,但可以重新赋值。
字符类型(rune)
Section titled “字符类型(rune)”var c1 byte = 'a' // ASCIIvar c2 rune = '中' // Unicode码点
fmt.Printf("%c %d\n", c1, c1) // a 97fmt.Printf("%c %U\n", c2, c2) // 中 U+4E2D
// rune是int32的别名c3 := rune(65) // 'A'Python对应:ord()和chr()
c = ord('a') # 97c = chr(97) # 'a'const PI = 3.14159const NAME = "Go"
// 批量声明const ( STATUS_OK = 200 STATUS_NOT_FOUND = 404 STATUS_SERVER_ERROR = 500)
// iota:常量生成器const ( Monday = iota // 0 Tuesday // 1 Wednesday // 2 // ...)Python对应:True, False, None是内置常量。
3.3 控制流:if/for/switch
Section titled “3.3 控制流:if/for/switch”本节目的:掌握Go控制流语法、对照Python理解差异
Python版本:
x = 10if x > 0: print("正数")elif x < 0: print("负数")else: print("零")Go版本:
x := 10if x > 0 { fmt.Println("正数")} else if x < 0 { fmt.Println("负数")} else { fmt.Println("零")}关键差异:
- 条件不需要括号
- 左大括号必须在同一行
// 正确if x > 0 { fmt.Println("正数")}
// 错误if x > 0{ fmt.Println("正数")}if与初始化:
// Go特有:if中可以初始化变量if err := doSomething(); err != nil { fmt.Println("错误:", err)}
// Python无等效语法,需要先赋值err = do_something()if err: print("错误:", err)常见模式:
if file, err := os.Open("test.txt"); err != nil { fmt.Println("打开失败:", err)} else { // file在此处可用 data := make([]byte, 100) file.Read(data) file.Close()}Python的for:
# 遍历范围for i in range(5): print(i) # 0 1 2 3 4
# 遍历列表for item in [1, 2, 3]: print(item)Go只有for(无while关键字):
// 经典forfor i := 0; i < 5; i++ { fmt.Println(i)}
// 模拟whilei := 0for i < 5 { fmt.Println(i) i++}
// 无限循环for { fmt.Println("无限循环") if condition { break }}
// 遍历切片items := []int{1, 2, 3}for index, value := range items { fmt.Printf("%d: %d\n", index, value)}
// 遍历字符串(UTF-8)str := "Hello世界"for i, r := range str { fmt.Printf("%d: %c\n", i, r)}range返回值:
| 类型 | 返回值 |
|---|---|
| 切片/数组 | index, value |
| Map | key, value |
| 字符串 | index, rune |
| Channel | value |
switch语句
Section titled “switch语句”Python的match(3.10+):
day = "Monday"match day: case "Monday": print("周一") case "Friday": print("周五") case _: print("其他")Go的switch:
day := "Monday"switch day {case "Monday": fmt.Println("周一")case "Friday": fmt.Println("周五")default: fmt.Println("其他")}Go的switch特点:
- 不需要break(自动break)
- 可以多个值
- 可以省略条件(当if-else用)
// 多个值switch day {case "Monday", "Tuesday", "Wednesday": fmt.Println("工作日")case "Saturday", "Sunday": fmt.Println("周末")}
// 无条件switch(替代if-else链)score := 85switch {case score >= 90: fmt.Println("A")case score >= 80: fmt.Println("B")case score >= 60: fmt.Println("C")default: fmt.Println("D")}
// fallthrough:继续执行下一个caseswitch 2 {case 1: fmt.Println("one") fallthroughcase 2: fmt.Println("two") fallthroughcase 3: fmt.Println("three")}// 输出: two three3.4 函数定义与返回值
Section titled “3.4 函数定义与返回值”本节目的:理解Go函数语法、多返回值、错误处理模式
Python版本:
def add(a, b): return a + b
result = add(1, 2)print(result) # 3Go版本:
func add(a int, b int) int { return a + b}
result := add(1, 2)fmt.Println(result) // 3函数声明语法:
func 函数名(参数1 类型1, 参数2 类型2) 返回类型 { // 函数体 return 值}Go最强大的特性之一:
// Python只能返回一个值def divide(a, b): return a // b # 如果用异常处理
// Go多返回值func divide(a, b int) (int, error) { if b == 0 { return 0, errors.New("除数不能为零") } return a / b, nil}
// 调用quotient, err := divide(10, 2)if err != nil { fmt.Println("错误:", err)} else { fmt.Println("结果:", quotient) // 5}忽略返回值:
result, _ := divide(10, 2) // 忽略errorfunc split(sum int) (x, y int) { x = sum * 4 / 9 y = sum - x return // 返回x和y(命名返回值)}
// 调用a, b := split(100)fmt.Println(a, b) // 44 56Python无等效特性。
// Pythondef sum(*args): total = 0 for n in args: total += n return total
print(sum(1, 2, 3)) # 6// Gofunc sum(nums ...int) int { total := 0 for _, n := range nums { total += n } return total}
fmt.Println(sum(1, 2, 3)) // 6// Go函数是一等公民(first-class)type Operation func(int, int) int
func add(a, b int) int { return a + b }func multiply(a, b int) int { return a * b }
func calculate(op Operation, a, b int) int { return op(a, b)}
func main() { result := calculate(add, 3, 4) fmt.Println(result) // 7
result = calculate(multiply, 3, 4) fmt.Println(result) // 12}Python同样支持函数作为参数。
- 优先用短声明:函数内
x := 10比var x int = 10更简洁;函数外用var - 零值是你的朋友:声明后直接使用的变量用
var x int,不必显式赋0 - 整数用int即可:除非需要特定宽度,Go的
int在64位系统是64位,足够日常使用 - for循环是唯一的循环:Go没有
while,用for实现所有循环模式(死循环for {}) - 多返回值配合error:Go没有异常机制,函数错误通过返回
error类型表达
| Python | Go |
|---|---|
x = 10 | var x int = 10 或 x := 10 |
int, float, str, bool | int, float64, string, bool |
if x > 0: | if x > 0 { } |
for i in range(n): | for i := 0; i < n; i++ { } |
for item in list: | for _, item := range list { } |
match x: | switch x { case ...: } |
def f(a, b): return a + b | func f(a, b int) int { return a + b } |
| 单一返回值 | 多返回值 func f() (int, error) |
| 无等效 | 命名返回值、指针、可变参数 |
- 声明int、float64、string、bool变量,用短声明和var两种方式
- 写一个函数,返回两个整数的和与积
- 写一个可变参数函数,计算任意数量整数的平均值
- 模拟Python的enumerate,用range遍历切片并打印索引和值
- 用switch实现一个简单的计算器(+、-、*、/)