面向 Go 开发者的 Zig 语言核心语法详解
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
try stdout.print("Hello, World!\n", .{});
}
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
const std = @import("std") 导入标准库!voidtry 处理可能错误的操作import "fmt"// 可变变量
var x: i32 = 10;
x = 20;
// 不可变变量
const y: i32 = 30;
// y = 40; // 编译错误
// 类型推断
var name = "Zig";
const version = 0.15;
// 可变变量
var x int = 10
x = 20
// 不可变变量
const y int = 30
// y = 40 // 编译错误
// 类型推断
name := "Go"
const version = 1.21
| 特性 | Zig | Go |
|---|---|---|
| 可变变量 | var x: i32 = 10; | var x int = 10 |
| 不可变变量 | const x: i32 = 10; | const x int = 10 |
| 类型推断 | var x = 10; | x := 10 |
| 全局变量 | var x: i32 = 10; | var x int = 10 |
| 类型类别 | Zig | Go | 说明 |
|---|---|---|---|
| 有符号整数 | i8, i16, i32, i64, i128 | int, int8, int16, int32, int64 | Zig 明确指定位数 |
| 无符号整数 | u8, u16, u32, u64, u128 | uint, uint8, uint16, uint32, uint64 | Zig 支持 128 位 |
| 浮点数 | f16, f32, f64, f128 | float32, float64 | Zig 支持更多精度 |
| 布尔值 | bool | bool | 相同 |
| 字符串 | []const u8 | string | Zig 更底层 |
// 固定大小数组
const arr: [5]i32 = [1, 2, 3, 4, 5];
// 切片(指针 + 长度)
var slice: []i32 = arr[1..4];
// 字符串切片
const msg: []const u8 = "Hello";
// 动态数组
var list = std.ArrayList(i32).init(allocator);
defer list.deinit();
// 固定大小数组
var arr [5]int = [5]int{1, 2, 3, 4, 5}
// 切片(动态数组)
slice := []int{1, 2, 3, 4, 5}
subslice := slice[1:4]
// 字符串
msg := "Hello"
// 动态数组(切片的底层)
list := make([]int, 0, 10)
// 基本函数
fn add(a: i32, b: i32) i32 {
return a + b;
}
// 多返回值
fn divide(a: i32, b: i32) struct { i32, i32 } {
return .{ a / b, a % b };
}
// 泛型函数
fn max(comptime T: type, a: T, b: T) T {
if (a > b) return a;
return b;
}
// 基本函数
func add(a int, b int) int {
return a + b
}
// 多返回值
func divide(a int, b int) (int, int) {
return a / b, a % b
}
// 泛型函数(Go 1.18+)
func max[T comparable](a T, b T) T {
if a > b {
return a
}
return b
}
fn 关键字comptime T: typefunc 关键字const x = 10;
if (x > 5) {
std.debug.print("大于5\n", .{});
} else if (x == 5) {
std.debug.print("等于5\n", .{});
} else {
std.debug.print("小于5\n", .{});
}
// switch 语句
switch (x) {
0...5 => std.debug.print("0-5\n", .{}),
6...10 => std.debug.print("6-10\n", .{}),
else => std.debug.print("其他\n", .{}),
}
x := 10
if x > 5 {
fmt.Println("大于5")
} else if x == 5 {
fmt.Println("等于5")
} else {
fmt.Println("小于5")
}
// switch 语句
switch x {
case 0, 1, 2, 3, 4, 5:
fmt.Println("0-5")
case 6, 7, 8, 9, 10:
fmt.Println("6-10")
default:
fmt.Println("其他")
}
// while 循环
var i: i32 = 0;
while (i < 5) {
std.debug.print("{d}\n", .{i});
i += 1;
}
// for 循环
const arr = [_]i32{ 1, 2, 3, 4, 5 };
for (arr) |value| {
std.debug.print("{d}\n", .{value});
}
// 带索引的循环
for (arr, 0..) |value, index| {
std.debug.print("{}: {d}\n", .{ index, value });
}
// for 循环(Go 只有 for)
for i := 0; i < 5; i++ {
fmt.Println(i)
}
// range 循环
arr := []int{1, 2, 3, 4, 5}
for _, value := range arr {
fmt.Println(value)
}
// 带索引的 range
for index, value := range arr {
fmt.Printf("%d: %d\n", index, value)
}
const std = @import("std");
pub fn main() !void {
// 创建分配器
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer std.debug.assert(gpa.deinit() == .ok);
const allocator = gpa.allocator();
// 分配内存
const buffer = try allocator.alloc(u8, 1024);
defer allocator.free(buffer);
// 使用内存
@memcpy(buffer[0..5], "Hello");
std.debug.print("{s}\n", .{buffer[0..5]});
}
package main
import "fmt"
func main() {
// 自动分配内存
buffer := make([]byte, 1024)
// 使用内存
copy(buffer[0:5], "Hello")
fmt.Println(string(buffer[0:5]))
// GC 自动清理
}
const std = @import("std");
// 定义错误
const Error = error{
DivisionByZero,
Overflow,
};
// 返回错误联合类型
fn divide(a: i32, b: i32) Error!i32 {
if (b == 0) {
return Error.DivisionByZero;
}
return a / b;
}
pub fn main() !void {
// 使用 try 传播错误
const result = try divide(10, 2);
// 显式错误处理
const err_result = divide(10, 0);
if (err_result) |value| {
std.debug.print("Success: {}\n", .{value});
} else |err| {
std.debug.print("Error: {}\n", .{err});
}
}
package main
import (
"errors"
"fmt"
)
// 定义错误
var ErrDivisionByZero = errors.New("division by zero")
var ErrOverflow = errors.New("overflow")
// 返回错误作为第二个值
func divide(a int, b int) (int, error) {
if b == 0 {
return 0, ErrDivisionByZero
}
return a / b, nil
}
func main() {
// 显式错误处理
result, err := divide(10, 2)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Success: %d\n", result)
}
const std = @import("std");
// 编译时计算斐波那契数列
fn fibonacci(comptime n: u32) u32 {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
// 编译时生成类型
fn Matrix(comptime T: type, comptime rows: usize, comptime cols: usize) type {
return struct {
data: [rows][cols]T,
pub fn init() @This() {
return @This(){
.data = std.mem.zeroes([rows][cols]T),
};
}
pub fn add(self: @This(), other: @This()) @This() {
var result = @This().init();
for (&result.data, self.data, other.data) |*r_row, s_row, o_row| {
for (r_row, s_row, o_row) |*r, s, o| {
r.* = s + o;
}
}
return result;
}
};
}
pub fn main() !void {
// 编译时计算
const fib10 = fibonacci(10);
std.debug.print("Fibonacci(10) = {}\n", .{fib10});
// 编译时生成类型
const Mat3x3 = Matrix(f32, 3, 3);
var m1 = Mat3x3.init();
var m2 = Mat3x3.init();
// 使用编译时生成的代码
const m3 = m1.add(m2);
}
Go 没有编译时计算特性,需要通过代码生成或接口来实现类似功能:
// Go 需要使用代码生成工具或接口
// 无法在运行时生成专门的类型
type Matrix struct {
Data [][]float64
Rows int
Cols int
}
func NewMatrix(rows, cols int) *Matrix {
data := make([][]float64, rows)
for i := range data {
data[i] = make([]float64, cols)
}
return &Matrix{
Data: data,
Rows: rows,
Cols: cols,
}
}
// 运行时检查类型
func (m *Matrix) Add(other *Matrix) (*Matrix, error) {
if m.Rows != other.Rows || m.Cols != other.Cols {
return nil, errors.New("matrix dimensions don't match")
}
// 运行时计算...
}