Zig vs Go: 상수, 변수 및 기본 타입

발행: (2026년 1월 15일 오전 09:15 GMT+9)
4 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 초기자는 불필요한 메모리 초기화를 피하게 해 주어 성능을 향상시킬 수 있습니다. 디버그 빌드에서는 안전성을 위해 메모리가 0으로 초기화될 수 있지만, 릴리스 빌드에서는 첫 번째 읽기 전까지 초기화되지 않은 상태로 남아 있을 수 있습니다.

정수 크기와 오버플로우

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는 정수의 정확한 비트 폭을 지정할 수 있습니다(예: 2비트 부호 없는 정수를 위한 u2). 기본적으로 산술 오버플로우가 발생하면 패닉이 발생합니다. 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은 명시적인 “module” 선언이 필요하지 않습니다.

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%...