目录 一、zlang简介 二、更新日志 三、技术专栏 3.1. 《zlang不需要getter、setter八股文》 3.2. 《构造和解析二进制数据包》 zlang是一门完全国产自研的、追求干净观感的、基于对象克隆、支持中文编程的编程语言: 完全从底层开始编写,语言引擎(词法 / 语法分析等)、对象库等均未基于 / 采用任何已有语言进行改造、包装或扩展,保证了代码和权利的干净、清晰与自主可控。 定位:简洁、高效、易上手、全栈能力,兼顾开发效率与运行性能。 设计理念:解决主流语言痛点(如 C 语言字符串处理繁琐、Java 冗余的 Getter/Setter),融合优势并加入创新设计。 对标语言:Python。 LOGO:中华狸花猫,象征独立、坚韧、不畏挑战。 一、Hello world import stdtypes stdio ; function int main( array args ) { stdout.Println( "Hello world" ); return 0; } 二、核心亮点(5 大特色) 1. 完全从底层自研,自主可控,国产编程语言 不基于任何其它语言/框架/引擎的改造或扩展,核心技术100%自研,真正自主可控; 产品起源于中国,完全中国制造,填补了国内原创编程语言领域的空白,和世界一起推动编程语言发展; 2. 原生中文编程,降低门槛 原生支持中文关键字和标识符,提供对中文编程的良好支持,打破英文编程的传统壁垒,适配国人的文字习惯,降低编程入门门槛,助力编程教育普及,让软件技术更贴合本土场景; 3. 创新语法设计,简洁高效 源于C/C++/Java又发展创新:C/Java的语法已经设计的相当完美了,新语言根本没必要完全设计一套新的语法,zlang语法继承自C/C++/Java,能让最广大同学们快速学习掌握; 极简哲学,万物皆对象:摒弃class,进化面向对象思想,声明变量即复制对象,简化和统一对象体系; 语义直观,减少冗余注解:支持带空格、符号、汉字等的标识符命名;在Web开发中,允许以HTTP 方法与 URL来定义函数名(如 function GET /api/user(){ ... }),无需额外注解,减少命名工作,让代码语义一目了然,大幅降低开发量; 以后不用写Getter/Setter繁琐代码了:没必要为了将来1%的扩展性导致99%都遵循繁琐的写法,zlang`提供了属性拦截器解决扩展性问题; 对异常处理体系的重新思考和实践; 吸取了很多语言的优秀精华:比如atomic、defer等; 4. 完整生态,开箱即用 官方标准库内置微整型、短整型、整形、长整型、浮点型、双浮点型、布尔型、字符串型、函数指针型等基础对象; 官方标准库内置数组、链表、映射、队列、栈、有序堆、树、缓冲区等数据容器; 官方标准库内置大数运算、日期时间、文件、输入输出、随机数、编码、缓存、JSON、XML、MSOffice、线程、日志等对象库; 官方标准库内置了加解密对象库,支持常用MD5、SHA1、SHA256、SHA512、DES、3DES、AES、RSA、SM2、SM3、SM4等算法,以及秘钥管理; 官方标准库内置了互斥量、读写锁、条件变量、内存屏障等线程同步机制; 官方标准库内置数据库对象库支持MySQL、PostgreSQL、Sqlite数据库; 官方标准库内置网络对象ip、netaddress、tcp、udp、http、httpclient、httpserver、htmlsection,自带高性能HTTP服务+网页模板引擎套装,支持Web应用开发; 官方还提供了跨平台图形界面库开源项目gtk-zlang,支持Windows、Linux桌面应用开发; 5. 高性能 + 跨平台 语言内核+对象库用C实现,耗时极低,压测验证性能稳定,静态网页 TPS 达 25000(5 并发),动态网页 RT 5~30ms(单个网页后端含 5 条结果集查询 SQL、23 条单记录查询 SQL、1 条插入 SQL)。 支持 Windows、Linux (glibc>=2.17) 跨平台编译与运行。 三、快速开始 源码仓库地址:https://gitee.com/calvinwilliams/zlang (仓库内含整套源代码、测试用例与详细介绍) 环境要求:Windows、Linux (glibc>=2.17) 四、关于作者 zlang由独立开发者calvinwilliams从零研发,历时多年打造。 zlang文档传送门 zlang技术专栏传送门 0.12.2.0 2026-08-13 calvin * 调整调试宏架构 * 对象zruntime新增函数PrintObjectBase(object)、PrintObjectFunctions(object)、PrintObjectProperties(object) * 解决对象内的属性集合实体的循环引用的缺陷 0.12.1.0 2026-08-09 calvin * 对象poller新增支持定时器 * 修复了原子机制的一个问题 0.12.0.0 2026-08-07 calvin * 对象eventfd新增函数SetFd、IsValid、GetFd * 对象thread、queue新增函数BindEventFd(eventfd)、GetFd;多路复用适用对象扩充到线程和消息队列了 * zlang启动参数新增"--child-*-level" 0.11.13.2 2026-08-05 calvin * 性能优化 0.11.13.1 2026-08-03 calvin * 内部做了小调整 * 回归测试脚本输出带颜色了 0.11.13.0 2026-07-31 calvin * 同步了network文档中的返回值和异常说明 * 新增对象eventfd * 现在子线程返回如果带致命错误会传递给主线程了 0.11.12.0 2026-07-30 calvin * ip对象新增函数CreateFromDefaultGateway、CreateFromViaConnectingGateway、SetFromDefaultGateway、SetFromViaConnectingGateway 0.11.11.0 2026-07-28 calvin * netaddress对象新增函数GetIpInteger、Create(uint,ushort)、Set(uint,ushort) * 对象-缓冲区转换函数支持跟踪当前偏移量了 * 修复了启动线程时未把当前对象和函数传入环境上下文的问题 * 调整了一批全局API名字 * 根对象新增函数GetDirectPropertySize、GetPropertiesDirectPropertySize 0.11.10.0 2026-07-27 calvin * 所有数值类对象都增加ToTiny~ToULong~ToDouble系列函数 * 各网络对象明确了超时类型、端口类型、数据长度类型,以及更新相关函数原型 * buffer对象新增函数ResizeElementCount、GetSize 0.11.9.1 2026-07-25 calvin * 重构了zexception对象,一劳永逸的解决了zexception和string加载优先级悖论 * 补充thread对象,如果是非守护线程,子线程结束后会把致命错误和异常传回主线程 0.11.9.0 2026-07-24 calvin * 新增pipe对象 * 对象poller支持pipe对象 0.11.8.0 2026-07-23 calvin * TEST_RUNTIME_LEVEL对内性能优化 * string对象增加内置小缓存区以减少内存块分配次数,整个string对象代码做了调整 * ZlangRuntime一些成员移到ZlangGlobalEnvironment,真正把ZlangGlobalEnvironment用起来 0.11.7.0 2026-07-22 calvin * 新增zlang命令行参数--builtin-parameters或-B用于显示所有内部缺省参数 * 修正了基础类型升级的问题 0.11.6.0 2026-07-21 calvin * 解开了一些类型检查硬性约束,更有适配性和灵活度 * 输出格式化增加内嵌非基础变量自动调用ToString * 重整C开发zlang对象库模板zlang_c_object而调整一些地方,完善文档 《zlang不需要getter、setter八股文》 getter、setter八股文 目前很多编程语言都有getter、setter八股文,本人很是反感,这也是创造zlang的主要原因之一。 getter、setter的作用是解耦 调用者代码 和 被调对象字段代码,其实现在IDE已经很智能了,换名字就是一键的事情。 Java class MyClass { private intage ; public MyClass() { } public int getAge() { return age; } public void setAge( int age ) { this.age = age ; } } public class Main { public static void main(String[] args) { MyClass o = new MyClass(); o.setAge(25); System.out.println(o.getAge()); } } zlang不需要getter、setter八股文 zlang设计成不需要getter、setter八股文,代码理解直观,代码量大幅减少,产出提效。 zlang object MyObject { intage ; } function int main( array args ) { MyObjecto ; o.age = 25 ; stdout.FormatPrintln( o.age ); } getter、setter允许“存取字段值时可以做一些转换” 还有人解释getter、setter允许“存取字段值时可以做一些转换”,你评估一下真实项目中有多少需要转换的需求,为了所谓的将来莫须有的扩展性,造成所有代码中都无谓充斥着大量getter、setter是一种愚蠢和低效。 Java class MyClass { private intage ; public MyClass() { } public int getAge() { return age; } public void setAge( int age ) { if (age < 0 || age > 300) { throw new IllegalArgumentException( "age invalid" ); this.age = age ; } } public class Main { public static void main(String[] args) { try { MyClass o = new MyClass(); o.setAge(25); System.out.println(o.getAge()); } catch (IllegalArgumentException e) { System.out.println("EXCEPTION:" + e.getMessage()); } } } `zlang有属性拦截器 你会问,那么将来有字段存取过程需要转换怎么办?zlang的回答是:用属性拦截器。1%的字段需要转换,就写1%的字段属性拦截器,而不是写100%的getter、setter,不多写一个字符,干净利落。 zlang import stdtypes stdio ; object MyObject { intage ; intercept set age( object age ) { if( age < 0 || age > 300 ) { zexception.SetException(-1,"age invalid"); return; } this.age = age ; return; } } function int main( array args ) { try { MyObjecto ; o.age = -1 ; stdout.FormatPrintln( o.age ); catch { stdout.Println( zexception.GetExceptionDesc() ); } } } 执行效果 $ zlang zlang_dont_need_getter_setter.z age invalid 《构造和解析二进制数据包》 zlang的缓冲区对象buffer特别适合构造和解析二进制数据包,下面以IP数据包为例,介绍zlang如何编写代码来构造和解析二进制数据包。 之所以选择IP数据包并不是鼓励用zlang处理网络协议栈,而是觉得IP数据包是典型的二进制数据包的研究案例。 构造总体思路 定义一个数据包对象,按顺序定义各字段(注意字段的字长;如果只取字段的几个比特,在字段名后面加上位域:(bit_fields);如果多个字段的位段映射到目标缓冲区中的一个字节,写对位域即可); 用缓冲区对象函数ResizeElementCount调整好缓冲区对象内部缓冲区大小; 为不影响父级对象,克隆子对象;填充子对象各字段的值;子对象缺省继承根对象zobject,调用根对象函数DumpBuffer倾倒到缓冲区对象缓冲区中; IP数据包头还有附带区域,可以在倾倒缓冲区后附加倾倒一个字符串; 倾倒后调用标准输出对象函数HexPrintln按十六进制打印输出缓冲区;(可选) 编写构造具体代码段 定义IP数据包对象: object ip_package { utinyversion:4 ; utinyihl:4 ; utinytos ; ushorttotal_length ; ushortidentification ; utinyflags:3 ; ushortfragment_offset:13 ; utinyttl ; utinyprotocol ; ushortheader_checksum ; uintsource_ip ; uintdest_ip ; } 调整好缓冲区对象内部缓冲区大小: ip_packet_head_size = ip_package.GetPropertiesDirectPropertySize() ; ip_packet_payload_size = (payload.Length()+4)/5*5 ; ip_packet_size = ip_packet_head_size + ip_packet_payload_size ; stdout.FormatPrintln( "ip_packet_head_size[%d]B + ip_packet_payload_size[%d]B = ip_packet_size[%d]B" , ip_packet_head_size , ip_packet_payload_size , ip_packet_size ); buf.ResizeElementCount( ip_packet_size ); 填充子对象各字段的值: ipp1..; ..version = 4b0100UT ; ..ihl = 5UT ; ..tos = 8b00000000UT ; ..total_length = ip_packet_size.ToUShort() ; ..identification = 0x1234US ; ..flags = 3b010UT ; ..fragment_offset = 4098US ; ..ttl = 64UT ; ..protocol = 6UT ; ..header_checksum = 0US ; ..source_ip = ip.CreateFromString("192.168.0.1").ToIntegerInHostOrder(); ..dest_ip = ip.CreateFromString("192.168.0.2").ToIntegerInHostOrder(); 倾倒各字段以及附带区域到缓冲区: offset = 0 ; ipp1.DumpBuffer( buf , offset ); buf.CopyIntoAsVString( offset , payload ); 按十六进制打印输出缓冲区: stdout.HexPrintln( buf ); 解析总体思路 已经定义好了数据包对象;拿到构造好的缓冲区对象; 设置解析偏移量为0,调用缓冲区对象函数ToEntityObject解析到数据包对象中各字段;偏移量自动前进; IP数据包头还有附带区域,计算出附带区域大小,调用缓冲区对象函数CopyOutAsVString解析到字符串中; 编写解析具体代码段 解析缓冲区对象到数据包对象中各字段: offset = 0 ; buf.ToEntityObject( <object>ipp2 , offset ); 解析附带区域: buf.CopyOutAsVString( offset , payload2 , buf.GetSize()-ip_package.GetPropertiesDirectPropertySize() ); 构造和解析的完整源代码 源文件名:tech-notes/binary-packet.z import stdtypes stdio network ; object ip_package { utinyversion:4 ; utinyihl:4 ; utinytos ; ushorttotal_length ; ushortidentification ; utinyflags:3 ; ushortfragment_offset:13 ; utinyttl ; utinyprotocol ; ushortheader_checksum ; uintsource_ip ; uintdest_ip ; } function void PrintlnIpPackage( ip_package ipp , string payload ) { stdout.FormatPrintln( "ipp.version[%{ipp.version}]" ); stdout.FormatPrintln( "ipp.ihl[%{ipp.ihl}]" ); stdout.FormatPrintln( "ipp.tos[%{ipp.tos}]" ); stdout.FormatPrintln( "ipp.total_length[%{ipp.total_length}]" ); stdout.FormatPrintln( "ipp.identification[0x%04x]" , ipp.identification ); stdout.FormatPrintln( "ipp.flags[%{ipp.flags}]" ); stdout.FormatPrintln( "ipp.fragment_offset[%{ipp.fragment_offset}]" ); stdout.FormatPrintln( "ipp.ttl[%{ipp.ttl}]" ); stdout.FormatPrintln( "ipp.protocol[%{ipp.protocol}]" ); stdout.FormatPrintln( "ipp.header_checksum[%{ipp.header_checksum}]" ); stdout.FormatPrintln( "ipp.source_ip[%s]" , ip.CreateFromIntegerInHostOrder(ipp.source_ip).ToString() ); stdout.FormatPrintln( "ipp.dest_ip[%s]" , ip.CreateFromIntegerInHostOrder(ipp.dest_ip).ToString() ); stdout.FormatPrintln( "ipp.payload[%s]" , payload ); return; } function int main( array args ) { try { ip_packageipp1 , ipp2 ; stringpayload = "helo" ; stringpayload2 ; intip_packet_head_size ; intip_packet_payload_size ; intip_packet_size ; buffer<char>buf ; intoffset ; ip_packet_head_size = ip_package.GetPropertiesDirectPropertySize() ; ip_packet_payload_size = (payload.Length()+4)/5*5 ; ip_packet_size = ip_packet_head_size + ip_packet_payload_size ; stdout.FormatPrintln( "ip_packet_head_size[%d]B + ip_packet_payload_size[%d]B = ip_packet_size[%d]B" , ip_packet_head_size , ip_packet_payload_size , ip_packet_size ); buf.ResizeElementCount( ip_packet_size ); ipp1..; ..version = 4b0100UT ; ..ihl = 5UT ; ..tos = 8b00000000UT ; ..total_length = ip_packet_size.ToUShort() ; ..identification = 0x1234US ; ..flags = 3b010UT ; ..fragment_offset = 4098US ; ..ttl = 64UT ; ..protocol = 6UT ; ..header_checksum = 0US ; ..source_ip = ip.CreateFromString("192.168.0.1").ToIntegerInHostOrder(); ..dest_ip = ip.CreateFromString("192.168.0.2").ToIntegerInHostOrder(); stdout.Println( "--- ipp1 ---"); PrintlnIpPackage( ipp1 , payload ); offset = 0 ; ipp1.DumpBuffer( buf , offset ); buf.CopyIntoAsVString( offset , payload ); stdout.HexPrintln( buf ); offset = 0 ; buf.ToEntityObject( <object>ipp2 , offset ); buf.CopyOutAsVString( offset , payload2 , buf.GetSize()-ip_package.GetPropertiesDirectPropertySize() ); stdout.FormatPrintln( "offset[%d]B" , offset ); stdout.Println( "--- ipp2 ---"); PrintlnIpPackage( ipp2 , payload2 ); catch { stdout.Println( zexception.GetExceptionDesc() ); } } return 0; } 执行效果 $ zlang binary-packet.z ip_packet_head_size[20]B + ip_packet_payload_size[5]B = ip_packet_size[25]B --- ipp1 --- ipp.version[4] ipp.ihl[5] ipp.tos[0] ipp.total_length[25] ipp.identification[0x1234] ipp.flags[2] ipp.fragment_offset[4098] ipp.ttl[64] ipp.protocol[6] ipp.header_checksum[0] ipp.source_ip[192.168.0.1] ipp.dest_ip[192.168.0.2] ipp.payload[helo] | 0 1 2 3 4 5 6 7 8 9 A B C D E F | 0123456789ABCDEF -----------+-------------------------------------------------+----------------- 0x00000000 | 45 00 00 19 12 34 50 02 40 06 00 00 C0 A8 00 01 | E....4P.@....... 0x00000010 | C0 A8 00 02 68 65 6C 6F 00 | ....helo. offset[25]B --- ipp2 --- ipp.version[4] ipp.ihl[5] ipp.tos[0] ipp.total_length[25] ipp.identification[0x1234] ipp.flags[2] ipp.fragment_offset[4098] ipp.ttl[64] ipp.protocol[6] ipp.header_checksum[0] ipp.source_ip[192.168.0.1] ipp.dest_ip[192.168.0.2] ipp.payload[helo]
zlang v0.12.2.0 发布,支持中文编程、支持Web开发/桌面应用开发的国产全自研编程语言
来源:开源中国
2026年08月26日 14:58
1 阅读
分享到: