前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Go程序员喜欢Ziglang?

Go程序员喜欢Ziglang?

作者头像
zouyee
发布2024-11-23 13:44:41
发布2024-11-23 13:44:41
14300
代码可运行
举报
文章被收录于专栏:Kubernetes GOKubernetes GO
运行总次数:0
代码可运行

在编程语言领域,Zig相对来说是新成员。Zig由Andrew Kelly创立,于2016年正式面世,Zig社区将其定位为“用于开发健壮、优化和可复用软件的通用编程语言”。作为一名Go开发者,我对Zig及其工具链的能力尤为感兴趣。在研究Zig时,发现这两种语言(Zig和Go)在某些方面有着共同的特性。

译|zouyee

为了帮助读者深入了解Kubernetes在各种应用场景下所面临的挑战和解决方案,以及如何进行性能优化。我们推出了<<Kubernetes经典案例30篇>>

在编程语言领域,Zig相对来说是新成员。Zig由Andrew Kelly创立,于2016年正式面世,Zig社区将其定位为“用于开发健壮、优化和可复用软件的通用编程语言”。

在这简单的描述中,可以发现其蕴含着一些宏大的目标。例如,Zig被视为一个能够与C语言竞争的编程语言(Rust在Linux内核方向进展更快一些)。此外,Zig提供一整套编译工具链,可以替代现有C编译器(Rust可以使用cargo-zigbuild跨平台编译)。

作为一名Go开发者,我对Zig及其工具链的提议尤为感兴趣。在研究Zig时,发现这两种语言(Zig和Go)在某些方面有着共同的特性。在这篇博文中,将重点介绍作为Go程序员,对Zig感兴趣的一些特性。

Ziglang与Go

简洁性

两种语言都秉承简洁的设计哲学,以减少语言的干扰,使开发者更快上手并能够高效地完成开发任务。Zig中没有宏、预处理器或操作符重载等功能,避免了执行流程中的“魔法”。

Go通过运行时处理内存分配和释放。而Zig则坚持其“无隐藏控制流”的准则,没有自动内存管理,而是通过标准库提供内存管理API,让开发者管理内存。

强类型

作为一门系统编程语言,Zig围绕类型系统设计了许多功能,注重安全性和C ABI(应用二进制接口)兼容性。这里简要介绍一些有趣的特性:

a. 有符号/无符号整数(预设大小从8位到128位)

b. 任意大小的有符号/无符号整数(例如i7表示7位整数)

c. 浮点数(精度从16位到128位)

d. 切片和数组(例如 `[]u8{‘h’, ‘i’, ‘!’}` 或 `[4]i32{1, 2, 3, 4}`)

e. 以UTF-8编码的字符串字面量,存储为以空字符结尾的字节数组

f. 具有丰富功能的结构体类型,可与C ABI兼容

g. 具有隐式/显式序数值的枚举,并支持方法

h. 可用于存储多种类型值的联合

i. 支持使用向量并行操作

j. 传统指针及多元素指针与切片表达式

错误处理

Zig中的错误处理机制非常有特色,融合了try-catch异常语义和Go的错误值模式。

首先,所有Zig错误都是必须分配和处理的值(否则会导致编译错误)。错误声明使用`error`关键字,如下所示:

代码语言:javascript
代码运行次数:0
复制
const DigitError = error{ TooLarge, };

有趣的是,Zig错误值可以与普通类型的值结合,使用`!`运算符形成一个联合类型。下面的函数可以返回错误或`u32`类型的值:

代码语言:javascript
代码运行次数:0
复制
fn addSingleDigits(a: u32, b: u32) !u32 {

    if (a > 9) return error.TooLarge;

    if (b > 9) return error.TooLarge;

    return a + b;

}

此外,Zig提供了类似Java等语言的`catch`关键字,用于错误处理:

代码语言:javascript
代码运行次数:0
复制
pub fn main() void {

    const result = addSingleDigits(4, 5) catch |err| {

        std.debug.print("Error: {}\n", .{err});

        return;

    };

    std.debug.print("Result: {}\n", .{result});

}

Zig还支持通过`try`关键字将错误向上级调用传播。此外,还可以通过`if-else-switch`语句更精确地筛选和处理错误。

Zig测试

在Zig中,测试是语言的关键性能力,使用`test`关键字声明:

代码语言:javascript
代码运行次数:0
复制
test "test that 1 + 1 equals 2" {

    const result = 1 + 1;

    assert(result == 2);

}

使用`zig test`命令运行源代码中的测试,在标准库中,测试大多跟源代码处于同一文件。

Zig运行

类似于`go run`,Zig提供了`zig run`命令,将编译和运行源代码的步骤结合:

代码语言:javascript
代码运行次数:0
复制
zig run my_program.zig

Defer

Zig与Go一样,通过`defer`概念来管理退出堆栈,当作用域块结束时执行清理操作等。

代码语言:javascript
代码运行次数:0
复制
const print = @import("std").debug.print;


fn addSingleDigits(a: u32, b: u32) !u32 {

    defer print("this is deferred!");
    

    if (a > 9) return error.TooLarge;

    if (b > 9) return error.TooLarge;

    return a + b;

}

Comptime

comptime是Zig的一项有趣特性。Zig没有单独的宏系统,而是通过comptime将其代码编写的灵活性扩展到编译阶段。

comptime允许在编译时进行如下操作:

a. 在编译时解析变量和表达式

b. 根据编译时值行为的函数

c. 编译期间有选择性地执行`comptime`代码块

d. 编译时执行的元编程

泛型

在 Zig 中,comptime提供了对类型值的访问,可以像普通数据值一样存储和传递这些类型值。

这使得可以创建带有类型参数的函数,如下所示:

代码语言:javascript
代码运行次数:0
复制
fn max(comptime T: type, a: T, b: T) T {

    return if (a > b) a else b;

}



test "max with different types" {

    const condition = false;

    const result = max(if (condition) f32 else u64, 1234, 5678);

    _ = result;

}

由于 comptime类型值被视为普通类型,Zig 允许使用它们来构建泛型数据结构。例如,MakeList使用 comptime 类型信息来返回一个编译时结构体:

代码语言:javascript
代码运行次数:0
复制
const std = @import("std");


fn MakeList(comptime T: type, comptime size: usize) type {

    return struct {

        items: [size]T,

    };

}



pub fn main() void {

    var list = MakeList(i32, 3){

        .items = [3]i32{1, 2, 3},

    };

    std.debug.print("List {}\n", .{list});

}

在这个示例中,`MakeList` 函数使用 `comptime` 类型和大小参数,返回一个包含固定数量元素的结构体。

Zig 编译

1. Zig作为 C (交叉) 编译器

Zig 工具链包含完整的 C 编译器,因此可以使用 Zig 来替换当前的 C 编译器工具链。以下是 `hello.c` 的源代码文件:

代码语言:javascript
代码运行次数:0
复制
#include <stdio.h>


int main(int argc, char **argv) {

    printf("Hello world\n");

    return 0;

}

使用以下命令,Zig 可以将该源代码编译成可执行的二进制文件:

代码语言:javascript
代码运行次数:0
复制
zig build-exe hello.c --library c

2. Zig 和 C 交叉编译

Zig 让交叉编译(无论是 C 代码还是 Zig 代码亦或Rust)变得简单。无需繁琐的“自行准备交叉编译工具链”。Zig 提供所有必要的工具和库,确保您可以面向其支持的任何架构进行编译。

例如,Zig 可以将上述 C 源代码交叉编译成一个面向 Linux 的静态二进制文件(使用 `musl` 库):

代码语言:javascript
代码运行次数:0
复制
zig build-exe hello.c --library c -target x86_64-linux-musl

3. Zig 和 CGo 交叉编译

Zig 对 C 的交叉编译对在交叉编译启用了 CGo 的 Go 源代码时特别有用。例如, `add.c` 中的C 函数 `add`:

代码语言:javascript
代码运行次数:0
复制
#include <stdint.h>

int32_t add(int32_t a, int32_t b) {

    return a + b;

}

我们可以在Go中 调用它:

代码语言:javascript
代码运行次数:0
复制
package main
/*

#include "add.c"

*/

import "C"

import (

    "fmt"

)



func main() {

    a, b := int32(3), int32(4)

    result := C.add(a, b)

    fmt.Printf("%d + %d = %d\n", a, b, result)

}

假设我们在 MacOS 上构建代码,可以使用命令 `zig cc` 来使用 Zig 的 C 编译器,将 C 代码交叉编译成目标文件并与 Go 的目标文件链接,以构建适用于 x86 架构 Linux 的静态二进制文件:

代码语言:javascript
代码运行次数:0
复制
CGO_ENABLED=1 GOOS=linux CC="zig cc -target x86_64-linux-musl" go build .

要让这一步成功,您只需安装 Zig 工具链,无其他依赖项!

Zig的突出特点

Zig致力于成为一个更好的C语言替代品,其不仅适用于低级系统编程,还适用于开发通用软件系统,具有以下突出特点:

设计简单

现代化语言的设计目标是提供一套设计良好的语法,而不像汇编语言那样原子化。如果语言的抽象过于接近汇编语言,开发人员可能需要编写冗长的代码。另一方面,当语言被抽象成接近人类可读时,它可能与硬件相距甚远,可能不适合系统编程的需求。

Zig提供了轻量级的、类Rust的语法,其大多数C提供的能力都已具备,但是它不提供Rust和C++那些复杂的功能集和语法,而是提供了一个像Go那样简单性为先的开发路径。

性能和安全性

性能和安全性是选择的关键因素。语言的性能通常取决于其标准库、核心运行时功能的性能,以及编译器生成的二进制文件的质量。同时,安全设计实现边界检查、溢出处理和内存范围,并帮助开发人员减少关键安全漏洞。

Zig构建系统提供了四种构建模式,开发人员可以根据其性能和安全性要求使用。Zig还可以在编译时理解变量溢出。

此外,它可以生成带有运行时安全检查的优化二进制文件,就像Rust一样,也可以生成不带运行时安全检查的超轻量级二进制文件,就像C一样。Zig官方文档声称,由于其基于LLVM的优化和改进的未定义行为,Zig在理论上比C更快!

完整的系统编程解决方案

大多数编程语言都有一个或多个标准编译器和标准库实现。例如,您可以使用以下编译C:

- GNU C

- Apple Clang

- 带有libc、BSD-libc和Microsoft C运行时的MSVC编译器

但是这两个组件对于现代系统编程需求来说还不够。程序员通常需要建立工具、包管理器和交叉编译工具等。

因此,在C生态系统中,像CMake、Ninja、Meson这样的构建工具以及类似Conan这样的包管理器逐渐流行,而像Go和Rust这样的现代语言官方内置了包管理器、构建工具及API、交叉编译支持和测试集成等。

与Go及Rust等现代语言一样,Zig内置了包管理器、构建系统及API、支持交叉编译和测试集成,这提高了Zig成为更好的C的机会,因为它解决了C(和C++)开发人员面临的关键系统编程问题。从语言设计的角度来看,Zig提供了C开发人员期望的现代语言的所有功能,因此C程序员可以逐步将他们的系统迁移到现代Zig,而无需重新编写他们遗留的代码库。

总结

本文,为您简单介绍了 Zig 的功能。Zig融合了简洁性、强大性、安全性和对 C 的兼容性,为开发者提供了一个令人兴奋的选择。无论您是为新项目寻找语言,还是像我一样想扩展编程技能,Zig 都是一个值得探索的创新选择。

Zig仍然是一种新语言,ZSF仍在定期实现和测试更多功能。学习Zig是一个很好的决定,因为它作为一种更好的C语言,有着光明的前景。

由于笔者时间、视野、认知有限,本文难免出现错误、疏漏等问题,期待各位读者朋友、业界专家指正交流。

参考文献

1.https://ziglang.org/documentation/master/.

2.https://medium.com/@vladimirvivien/things-i-like-about-zig-as-a-go-programmer-75eb02aab00f

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-11-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DCOS 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档