在中篇里,我们将继续深入对比Go和Zig的语法,着重探讨控制流语句、数组与切片以及内存管理方面的差异。
一、控制流语句
- 条件语句
- Go:
package main
import "fmt"
func main() {
num := 10
if num > 5 {
fmt.Println("num 大于 5")
} else {
fmt.Println("num 小于等于 5")
}
}
Go的if语句条件部分无需括号,可直接跟代码块。还支持在if语句里声明变量,变量作用域仅限于if语句块。
- Zig:
const std = @import("std");
pub fn main() void {
var num: i32 = 10;
if (num > 5) {
std.debug.print("num 大于 5\n", .{});
} else {
std.debug.print("num 小于等于 5\n", .{});
}
}
Zig的if语句条件部分需要括号,整体结构与Go类似,但语句结尾需分号。
- 循环语句
- Go:
package main
import "fmt"
func main() {
for i := 0; i < 5; i++ {
fmt.Println(i)
}
numbers := []int{1, 2, 3}
for index, value := range numbers {
fmt.Printf("索引: %d, 值: %d\n", index, value)
}
}
Go的for循环有多种形式,经典的for init; condition; post形式,还有for range用于遍历数组、切片、映射等。
- Zig:
const std = @import("std");
pub fn main() void {
var i: u32 = 0;
while (i < 5) : (i += 1) {
std.debug.print("{}\n", .{i});
}
var numbers = [_]i32{1, 2, 3};
for (numbers) |value, index| {
std.debug.print("索引: {}, 值: {}\n", .{index, value});
}
}
Zig没有像Go那样经典的for循环形式,常用while循环。for循环用于遍历数组,|value, index|语法用于获取元素值和索引。
二、数组与切片
- 数组
- Go:
package main
import "fmt"
func main() {
var arr [3]int = [3]int{1, 2, 3}
fmt.Println(arr)
}
Go中数组长度是类型的一部分,声明时需指定长度。
- Zig:
const std = @import("std");
pub fn main() void {
var arr = [3]i32{1, 2, 3};
std.debug.print("{any}\n", .{arr});
}
Zig的数组声明类似Go,但初始化时[3]表明数组长度,i32指定元素类型。
- 切片
- Go:
package main
import "fmt"
func main() {
slice := []int{1, 2, 3}
slice = append(slice, 4)
fmt.Println(slice)
}
Go的切片是动态数组,使用append函数可动态添加元素。
- Zig:
const std = @import("std");
pub fn main() void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
var allocator = arena.allocator();
var slice = std.ArrayList(i32).init(allocator);
defer slice.deinit();
try slice.append(1);
try slice.append(2);
try slice.append(3);
try slice.append(4);
std.debug.print("{any}\n", .{slice.items});
}
Zig中没有像Go那样内置的切片类型,使用std.ArrayList实现类似功能。需要手动管理内存,使用try处理可能的错误。
三、内存管理
- Go:
package main
import "fmt"
func main() {
var num *int
value := 10
num = &value
fmt.Println(*num)
}
Go有自动垃圾回收机制,开发者无需手动管理内存。使用指针操作变量地址。
- Zig:
const std = @import("std");
pub fn main() void {
var num: i32 = 10;
var ptr: *i32 = #
std.debug.print("{}\n", .{ptr.*});
}
Zig没有自动垃圾回收,开发者需手动管理内存。指针操作与Go类似,但要更关注内存的分配和释放。
总结
中篇我们对比了Go和Zig在控制流语句、数组与切片以及内存管理方面的语法差异。Zig在语法上与Go有一些相似之处,但也有很多独特的地方,特别是在内存管理上需要开发者更加谨慎。下篇我们将探讨结构体、接口、并发编程等内容。