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

발행: (2026년 1월 15일 오전 09:15 GMT+9)
4 분 소요
원문: 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

관련 글

더 보기 »

Go의 비밀스러운 삶: Concurrency

경쟁 조건(race condition)의 혼란에 질서를 부여한다. Chapter 15: Sharing by Communicating 아카이브는 그 화요일에 유난히 시끄러웠다. 목소리 때문이 아니라 t...

Go에서 우아한 도메인 주도 설계 객체

❓ Go에서 도메인 객체를 어떻게 정의하시나요? Go는 전형적인 객체‑지향 언어가 아닙니다. Domain‑Driven Design(DDD) 같은 개념을 구현하려고 할 때, 예를 들어 En…

경량 크로스플랫폼 Hosts 관리 도구

소개 Go Hosts는 Go + Fyne으로 개발된 가벼운 크로스 플랫폼 Hosts 관리 도구로, Windows와 macOS(Intel)를 지원합니다. 용량이 큰 Electron 애플리케이션(예: SwitchHosts)과 비교했을 때, Go Hosts는 더 작고 컴파일 및 패키징이 유연하여 작은 도구에 집착하는 사용자에게 적합합니다. - GitHub 오픈소스 주소...