Zig 与 Go:常量、变量和基本类型
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});
通过分配内存并复制常量数据,字符串变为可变的,从而可以进行就地修改。