Sintaxis básica de Zig

Zig es un nuevo lenguaje de programación, simple y eficiente por diseño, y directamente compatible con C.

A continuación se presentan algunos conceptos básicos de la sintaxis de Zig para ayudarte a empezar rápidamente.

La extensión de los archivos de código Zig es.zig。


El primer programa en Zig

Primero veamos el programa "Hello, World!" en Zig.

Primero inicialicemos un proyecto Zig:

mkdir hello-world
cd hello-world
zig init

Luego, crea el archivo hello.zig en ese proyecto, con el siguiente código:

Ejemplo (archivo hello.zig)

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    try stdout.print("Hello, World!\n", .{});
}

Análisis del código:

1. Importar la biblioteca estándar:

const std = @import("std");

Esta línea importa la biblioteca estándar de Zig, similar a la de C.#include <stdio.h>。

2. Definir la función main:

pub fn main() !void

pubLa palabra clave indica que esta función es pública,fnla palabra clave se usa para definir funciones,maines el punto de entrada de la función. El tipo de retorno!voidindica que la función no devuelve un valor, pero puede devolver un error (!el prefijo indica un tipo de unión de error).

3. Obtener la salida estándar:

const stdout = std.io.getStdOut().writer();

Obtén el writer de la salida estándar a través de la biblioteca estándar y luego llama a sus métodos para escribir contenido.

4. Imprimir "Hello, World!":

try stdout.print("Hello, World!\n", .{});

printEl método escribe la cadena formateada en la salida estándar,.{}es una lista de parámetros vacía.tryLa palabra clave propaga el error hacia arriba al llamador cuando ocurre un error.

Este programa muestra algunas características básicas del lenguaje Zig, como la definición de funciones, el uso de la biblioteca estándar y el manejo de errores.

Si solo quieres ejecutar un único archivo, puedes usar directamente:

zig run hello.zig

Si quieres compilarlo como un ejecutable, usa:

zig build-exe hello.zig

Después de compilar, ejecuta en la terminal:

./hello

Esto mostrará:

Hello, World!

Identificadores

En Zig, los identificadores son nombres utilizados para nombrar variables, funciones, tipos, etc.

A continuación se presentan algunas reglas y características sobre los identificadores en Zig:

  1. Letras y números: Los identificadores pueden contener letras (A-Z y a-z), números (0-9) y guiones bajos (_).

  2. Carácter inicial: Los identificadores deben comenzar con una letra o un guion bajo, y no pueden comenzar con un número.

  3. Sensibilidad a mayúsculas y minúsculas: Zig es un lenguaje sensible a mayúsculas y minúsculas, lo que significa queVariableyvariableson dos identificadores diferentes.

  4. Palabras clave y palabras reservadas: Algunas palabras específicas están reservadas en Zig y no pueden usarse como identificadores. Por ejemplofn(función),struct(estructura),if(sentencia condicional), etc.

  5. Convenciones de nomenclatura: Zig recomienda oficialmente las siguientes convenciones:

    • camelCase (notación camello en minúscula): Se usa para nombres de variables y funciones. Por ejemplomyVariable、calculateSum。
    • PascalCase (notación camello en mayúscula): Se usa para nombres de tipos y espacios de nombres. Por ejemploPoint、ArrayList。
    • SCREAMING_SNAKE_CASE: Se usa para constantes conocidas en tiempo de compilación (constantes comptime). Por ejemploMAX_SIZE。
  6. Tipos opcionales: Zig tiene un tipo especial?T, que representa un valor opcional de tipoT. Esto es muy útil cuando se manejan valores que podrían ser nulos.

  7. Constantes en tiempo de compilación: Usa la palabra clavecomptimeantes del identificador para indicar que es una constante en tiempo de compilación.

  8. Tipos de error: Usa la palabra claveerrorpara definir tipos de error, por ejemplo:

    pub fn openFile(path: []const u8) !void {
        // ...
    }
  9. Sufijo de tipo: Usar el sufijo_tdespués del nombre del tipo es una costumbre del lenguaje C; en Zig también se puede hacer, pero no es necesario.

Palabras clave reservadas

A continuación se presentan algunas palabras clave reservadas en Zig:

KeywordsDescription
alignEspecifica el número de bytes de alineación de una variable o tipo
allowzeroPermite que un puntero apunte a un valor nulo
andOperación Y lógica
asmBloque de ensamblador en línea
breakSale del bucle o ámbito más cercano
callconvConvención de llamada
constDefine una constante
continueContinúa con la siguiente iteración del bucle
deferEjecuta la sentencia de forma diferida hasta que se sale del ámbito
elseRama negativa de una sentencia condicional
enumTipo enumerado
errdeferSentencia de ejecución diferida cuando ocurre un error
errorDefinición de tipo de error
exportExporta símbolos para que puedan ser llamados desde C, etc.
fnDefinición de función
forBucle de iteración
ifSentencia condicional
inlineFunción inline o bucle inline
linksectionEspecifica la sección del enlazador
noaliasUn puntero no puede ser alias de otro puntero
noinlineEvita la inserción inline de una función
nullValor nulo de un tipo opcional
orOperación O lógica
packedElimina el relleno de la estructura, disponiendo los campos de forma compacta a nivel de bits
pubNivel de acceso público (public)
returnRetorna desde una función
structDefinición de tipo de estructura
switchSentencia de selección con múltiples ramas
testBloque de código de prueba
threadlocalVariable local al hilo
tryIntenta ejecutar una expresión y propaga el error hacia arriba si ocurre
unionDefinición de tipo de unión
usingnamespaceIntroduce todos los miembros públicos de un espacio de nombres en el ámbito actual
varDefine una variable mutable
voidSin tipo; se usa a menudo para funciones que no devuelven un valor
whileSentencia de bucle

Sintaxis básica

1. Variables y constantes

En Zig, las variables se definen convarla palabra clave para definirlas, y las constantes conconstla palabra clave para definirlas.

const x: i32 = 10;  // 定义一个整数常量 x,值为 10
var y: f64 = 3.14;  // 定义一个浮点数变量 y,值为 3.14

2. Funciones

Las funciones se definen con la palabra clavefnpara definirlas, y se especifica el tipo de retorno.

const std = @import("std");

fn add(a: i32, b: i32) i32 {
    return a + b;
}

pub fn main() !void {
    const result = add(3, 4);
    const stdout = std.io.getStdOut().writer();
    try stdout.print("Result: {}\n", .{result});
}

3. Sentencias condicionales

Se usaifyelsepara implementar la lógica condicional.

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    const number = 10;
    if (number > 0) {
        try stdout.print("Number is positive\n", .{});
    } else {
        try stdout.print("Number is not positive\n", .{});
    }
}

4. Bucles

Zig admitewhileyforbucles.

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    // while 循环,: (i += 1) 是每次迭代后执行的更新表达式
    var i: i32 = 0;
    while (i < 5) : (i += 1) {
        try stdout.print("i: {}\n", .{i});
    }

    // for 循环,遍历数组
    const array = [5]i32{ 1, 2, 3, 4, 5 };
    for (array) |item| {
        try stdout.print("item: {}\n", .{item});
    }
}

5. Estructuras

Zig usastructpara definir estructuras.

const std = @import("std");

const Point = struct {
    x: i32,
    y: i32,
};

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    const p = Point{ .x = 10, .y = 20 };
    try stdout.print("Point: ({}, {})\n", .{ p.x, p.y });
}

6. Manejo de errores

Zig usa tipos de error enumerados y la palabra clavetry / catchpara el manejo de errores.

const std = @import("std");

const FileError = error{
    FileNotFound,
};

fn readFile(path: []const u8) !void {
    // 模拟一个可能失败的操作
    if (std.mem.eql(u8, path, "invalid")) {
        return FileError.FileNotFound;
    }
    // 其他操作...
}

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    readFile("invalid") catch |err| {
        switch (err) {
            FileError.FileNotFound => {
                try stdout.print("Error: File not found\n", .{});
            },
            else => return err,
        }
        return;
    };

    try stdout.print("File read successfully\n", .{});
}

Análisis del código:

  • catch |err|: Captura el error y lo vincula a una variableerr。
  • switch (err): Compara los tipos de error y maneja por separado los diferentes casos de error.
  • else => return err: Propaga directamente los errores inesperados hacia arriba, sin ignorarlos silenciosamente.
  • SireadFilese ejecuta correctamente (sin activar catch), se continúa con la sentencia de impresión posterior.
Otras extensiones