Zig 与 Go:常量、变量和基本类型

发布: (2026年1月15日 GMT+8 08:15)
3 min read
原文: Dev.to

Source: Dev.to

作为两种静态且强类型的语言,Go 和 Zig 在常量和变量的定义方式上有许多相似之处。两者都需要显式类型或依赖类型推断。

常量和变量

Go

func main() {
    const myInt int32 = 123
    // typed by inference
    myFloat := 12.34
    fmt.Printf("integer: %d - float: %f\n", myInt, myFloat)
    myFloat = 45.67
    fmt.Printf("integer: %d - float: %f\n", myInt, myFloat)

    // zero value assigned
    var myBoolean bool
    fmt.Printf("boolean: %t\n", myBoolean)
    myBoolean = true
    fmt.Printf("boolean: %t\n", myBoolean)

    // print types
    fmt.Printf("%T - %T - %T\n", myInt, myFloat, myBoolean)
}

Zig

pub fn main() !void {
    const myInt: i32 = 123;
    var myFloat = 12.34;
    myFloat = 45.67;
    // typed by inference
    const myBoolean = true;
    std.debug.print("integer: {d} - float: {d} - boolean: {}\n", .{ myInt, myFloat, myBoolean });
    // print types
    std.debug.print("{} {} {}\n", .{ @TypeOf(myInt), @TypeOf(myFloat), @TypeOf(myBoolean) });

    // no zero value in Zig
    var undefinedValue: f32 = undefined;
    std.debug.print("undefined value: {d}\n", .{undefinedValue});
    undefinedValue = 73.123;
    std.debug.print("assigned value: {d}\n", .{undefinedValue});
}

Zig 的 undefined 初始化器避免了不必要的内存初始化,从而可以提升性能。在调试构建中,出于安全考虑内存可能会被零初始化,而在发布构建中则可能保持未初始化状态直至首次读取。

整数大小与溢出

Go(默认溢出行为)

var myNumber uint8 = 255
fmt.Printf("value : %d\n", myNumber)
myNumber += 1
fmt.Printf("value overflow tolerated : %d\n", myNumber) // wraps around to 0

Zig(显式溢出处理)

var myNumber: u2 = 3;
std.debug.print("number {d} of type {}\n", .{ myNumber, @TypeOf(myNumber) });
myNumber += 1; // panic error! (overflow)

Zig 允许指定整数的精确位宽(例如 u2 表示 2 位无符号整数)。默认情况下,算术溢出会触发 panic。若想获得类似 Go 的环绕语义,Zig 提供了诸如 %+ 的溢出感知运算符。

字符串

Zig 没有专门的字符串类型;字符串被视为字节数组(u8)。字符串字面量会成为只读数组,嵌入到二进制中。

// hard‑coded string is a pointer to a read‑only array
const myConstString: *const [14:0]u8 = "hello ziguanas";
std.debug.print("const string {s}\n", .{myConstString});
std.debug.print("len and size of myConstString: {d} - {d}\n",
    .{ myConstString.len, @sizeOf(@TypeOf(myConstString.*)) });
std.debug.print("first value of string {d} formatted as char \"{c}\"\n",
    .{ myConstString[0], myConstString[0] });

分配可变字符串

// create allocator
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
var allocator = gpa.allocator();

// allocate memory for the string
var myStringAllocation = try allocator.alloc(u8, myConstString.len);
defer allocator.free(myStringAllocation);

// copy the constant string into the allocation
@memcpy(myStringAllocation, myConstString);
std.debug.print("allocated string before edit: {s}\n", .{myStringAllocation});

// mutate the string
myStringAllocation[0] = 'H';
std.debug.print("allocated string after edit: {s}\n", .{myStringAllocation});

通过分配内存并复制常量数据,字符串变为可变的,从而可以进行就地修改。

Back to Blog

相关文章

阅读更多 »

Zig vs Go:init 和 run

初始化 在 Go 中,我们使用以下方式初始化模块: ```bash go mod init module-name ``` 在 Zig 中,等价的操作非常简单: ```bash zig init ``` Zig 不需要显式的“模块”声明。

Gin vs Spring Boot:详细比较

封面图片:Gin vs Spring Boot:详细比较 https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%...