news 2026/10/13 1:44:17

Wing 标准库 String(str)类型 API 完全指南:从字符串操作到 JSON 安全转换

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Wing 标准库 String(str)类型 API 完全指南:从字符串操作到 JSON 安全转换
  • 编程语言
  • 编译器
  • 云原生
  • 语言运行时

【免费下载链接】wing

A programming language for the cloud ☁️ A unified programming model, combining infrastructure and runtime code into one language ⚡

项目地址:https://gitcode.com/gh_mirrors/wi/wing
点击查看免费下载

导读

本文以 docs/api/04-standard-library/std/string.md 中定义的String类 API 为骨架,系统讲解 Wing 语言内置字符串类型str的全部方法:字符访问、子串查询、大小写转换、查找替换、拆分合并、去除空白,以及将Json安全转换为str的静态方法fromJson。读完本文,你将掌握str类型每一个方法的签名、参数语义、边界行为与典型用法,并能借助仓库中的源码实现与测试用例理解其底层机制,在编写云端应用(如日志解析、请求参数校验、数据格式化)时熟练运用。

str是 Wing 语言的原生(primitive)类型之一,在 docs/api/05-language-reference.md 中被描述为UTF-16 编码的字符串,其完整 API 由 SDK 中的String类暴露给编译器,语言层面通过@wingType str注解将其绑定为str关键字(见 packages/@winglang/sdk/src/std/string.ts)。

一、字符串字面量与基础性质

1.1 字符串字面量:插值、多行与转义

在 Wing 中,字符串用双引号声明,并且所有声明形式都支持多行。普通字符串内部会处理形如{<expression>}的表达式替换(插值),行为类似于 JavaScript 的`text ${sub.prop}`模板字符串,同时支持 Unicode 转义序列;在插值表达式内部,"与{可以通过反斜杠\转义。参见 docs/api/05-language-reference.md:

let name = "World"; let s = "Hello, {name}!"; let l = s.length; // 11

字符串连接也可以直接使用+运算符与+=赋值运算符。来自 tests/valid/std_string.test.w 的验证:

assert("hello" + " world" == "hello world"); let var initial = "hey, "; initial += "you"; assert(initial == "hey, you");

多行字符串中的换行与显式\n转义是等价的:

let s3 = "hello world"; let s4 = "hello\nworld"; assert(s3 == s4);

1.2length属性

String类暴露的唯一属性,类型为num,表示字符串的长度(UTF-16 编码下的字符数量)。

length: num;
assert("hello".length == 5); assert("".length == 0);

示例与边界行为均可在 tests/sdk_tests/std/string.test.w 中验证:空字符串长度为0。

二、查询类方法:contains、startsWith、endsWith、indexOf

这组方法用于判断字符串是否包含某个子串,或在何处出现,返回值均为bool/num。

2.1contains(searchString: str): bool

检查字符串是否包含指定子串(区分大小写)。

contains(searchString: str): bool
assert("hello wing".contains("hello")); assert(!"hello wing".contains("Hello")); // 大小写敏感 assert("hello wing".contains("w"));

2.2startsWith(searchString: str): bool与endsWith(searchString: str): bool

分别判断字符串是否以给定子串开头 / 结尾。

startsWith(searchString: str): bool endsWith(searchString: str): bool
assert("hello wing".startsWith("h")); assert(!"hello wing".startsWith("H")); // 大小写敏感 assert(!"hello wing".startsWith("w")); assert("boom".endsWith("m")); assert(!"boom".endsWith("b"));

2.3indexOf(searchString: str): num

返回searchString在字符串中第一次出现的索引(从 0 开始);若未找到,返回-1。

indexOf(searchString: str): num
assert("boom".indexOf("m") == 3); assert("boom".indexOf("a") == -1); // 未找到返回 -1

上述四类查询的测试用例见 tests/sdk_tests/std/string.test.w 与 tests/sdk_tests/std/string.test.w。

三、提取与切片:at、substring

3.1at(index: num): str

返回指定索引处的单个字符。关键特性:支持负索引,负数从字符串末尾倒数计数。越界(索引超出[0, length)或负索引超出范围)会抛出运行时错误"index out of bounds"。

at(index: num): str
assert("boom".at(0) == "b"); assert("boom".at(2) == "o"); // 负索引:从末尾倒数 assert("boom".at(-1) == "m"); assert("boom".at(-4) == "b"); // 越界抛出异常 // "boom".at(4) -> Error: index out of bounds // "boom".at(-5) -> Error: index out of bounds

在源码 packages/@winglang/sdk/src/std/string.ts 中,at通过一条@macro编译期展开实现越界检查:

if ($args$ >= $self$.length || $args$ + $self$.length < 0) { throw new Error("index out of bounds") }

也就是说,越界保护在编译期由宏生成,运行时由 JS 层执行。完整测试见 tests/sdk_tests/std/string.test.w。

3.2substring(indexStart: num, indexEnd?: num): str

截取从indexStart开始、到indexEnd结束(不含indexEnd)的子串。indexEnd为可选参数,省略时截取到字符串末尾。

substring(indexStart: num, indexEnd?: num): str
assert("hello wing".substring(0, 5) == "hello"); assert("hello wing".substring(5) == "wing"); assert("hello wing".substring(5, 7) == "wi"); // 超出末尾的结束索引会被安全截断到字符串长度 assert("hello wing".substring(0, 100) == "hello wing");

测试见 tests/sdk_tests/std/string.test.w 与 tests/valid/std_string.test.w。

四、修改与变换:replace、replaceAll、lowercase、uppercase、trim、concat、split

这组方法产生新的字符串(或数组),原始字符串不变——str是不可变类型。

4.1replace(searchString: str, replaceString: str): str与replaceAll(searchString: str, replaceString: str): str

  • replace:只替换第一次出现的子串。
  • replaceAll:替换所有出现的子串。
replace(searchString: str, replaceString: str): str replaceAll(searchString: str, replaceString: str): str
assert("foo".replace("o", "0") == "f0o"); // 只替换第一处 assert("foo".replaceAll("o", "0") == "f00"); // 替换全部 assert("hello world".replace("world", "wing") == "hello wing"); assert("hello world world".replaceAll("world", "wing") == "hello wing wing"); assert("hello world".replace("wing", "☁") == "hello world"); // 未命中则原样返回 assert("hello world world".replaceAll(" ", "-") == "hello-world-world"); assert("".replace("", "hello world") == "hello world"); // 空字符串也能匹配

replace在源码中通过@macro $self$.replace(...$args$)展开为 JS 原生方法,replaceAll展开为$self$.replaceAll(...$args$)(见 packages/@winglang/sdk/src/std/string.ts)。完整测试见 tests/sdk_tests/std/string.test.w。

4.2lowercase(): str与uppercase(): str

分别返回全小写 / 全大写的新字符串。对非字母字符(数字、符号)无影响。

lowercase(): str uppercase(): str
assert("BOOM".lowercase() == "boom"); assert("BooM".lowercase() == "boom"); assert("123#@".lowercase() == "123#@"); assert("BooM".uppercase() == "BOOM"); assert("boom".uppercase() == "BOOM"); assert("123#@".uppercase() == "123#@");

源码中二者分别通过宏展开为 JS 的toLocaleLowerCase()与toLocaleUpperCase()(见 packages/@winglang/sdk/src/std/string.ts 与 packages/@winglang/sdk/src/std/string.ts),即遵循本地化规则进行大小写转换。测试见 tests/sdk_tests/std/string.test.w。

4.3trim(): str

移除字符串首尾的空白字符(空格、制表符\t、换行\n等),不处理字符串内部的空白。

trim(): str
assert("hello wing ".trim() == "hello wing"); assert("\thello wing\n".trim() == "hello wing"); assert("".trim() == ""); assert(" some string ".trim() == "some string");

测试见 tests/sdk_tests/std/string.test.w。

4.4concat(strN: str): str

将一个(或多个)字符串拼接在当前字符串之后,返回新的字符串。

concat(strN: str): str
assert("boom".concat("boom") == "boomboom"); assert("some string".concat("s are immutable") == "some strings are immutable");

测试见 tests/sdk_tests/std/string.test.w。

4.5split(separator: str): MutArray<str>

按分隔符将字符串拆分为可变字符串数组MutArray<str>。特别地,传入空字符串""作为分隔符时,会按单个字符逐个拆分。

split(separator: str): MutArray<str>
assert("hello;wing".split(";").at(0) == "hello"); assert("hello;wing".split(";").at(1) == "wing"); assert("hello wing".split(" ").at(0) == "hello"); // 空分隔符按字符拆分 assert("hello wing".split("").length == 10); assert("hello wing".split("").at(0) == "h"); assert("hello wing".split("").at(1) == "e");

测试见 tests/sdk_tests/std/string.test.w。split常与Json.stringify配合输出结构化结果(见下文实战示例)。

五、静态方法fromJson:从Json安全转换字符串

5.1 签名与语义

String类还提供唯一的静态方法,用于把Json值安全转换为强类型字符串:

str.fromJson(json: Json, options?: JsonValidationOptions): str
  • json(必填):要转换为字符串的Json值。
  • options(可选):JsonValidationOptions类型,来自 packages/@winglang/sdk/src/std/json.ts,目前仅包含一个字段:
字段类型说明
unsafebool?设为true时跳过运行时类型校验(可能引发运行时错误)

5.2 为什么需要fromJson:动态 JSON 的类型安全

在 Wing 中,仅当Json字面量在程序中静态可见时,才能直接赋值给str变量;对于来自外部(如http.get()的响应)的动态Json,直接赋值会编译报错。此时必须使用fromJson()进行带运行时校验的转换。参见 docs/api/05-language-reference.md:

let jsonString = Json "hello"; let myStr = str.fromJson(jsonString);

5.3 运行时校验与失败行为

fromJson的底层实现位于 packages/@winglang/sdk/src/std/string.ts:它通过JsonSchema构造type: "string"的 schema 并对输入json执行校验,校验不通过时抛出错误。语言参考给出的失败示例:

str.fromJson(Json 123); // RUNTIME ERROR: unable to parse number `123` as a string.

测试 tests/sdk_tests/std/string.test.w 中定义了错误信息常量PARSE_ERROR = "unable to parse string",并断言传入Json 123会抛出包含该文本的异常:

let PARSE_ERROR = "unable to parse string"; assert(str.fromJson(Json "Hello") == "Hello"); // str.fromJson(Json 123); // 抛出 "unable to parse string"

num.fromJson、bool.fromJson等其余基础类型同理(见 tests/valid/json_static.test.w 中str.fromJson(jsonOfMany.get("b")) == "hello"的用法)。

5.4 相关的tryFromJson与unsafe

fromJson校验失败会抛异常;若希望以可选值方式处理失败,语言参考介绍了配套的tryFromJson()方法,返回str?,可与??配合提供默认值(docs/api/05-language-reference.md):

let s = str.tryFromJson(myJson) ?? "invalid string";

当确信Json值类型正确、希望跳过运行时校验换取性能时,可传入unsafe: true:

str.fromJson(Json 10, unsafe: true); // 跳过校验,自行承担类型风险

上述用法在 tests/valid/struct_from_json.test.w 与语言参考的 schema validation 章节中均有体现。

六、实战示例:完整运行与预期输出

官方 by-example 章节 docs/by-example/21-string-functions.md 给出了一个覆盖本文多数 API 的可直接运行的main.w,其自动化生成版本位于 tests/doc_examples/valid/21-string-functions.md_example_1/main.w:

log("test".contains("es")); log("test".length); log("test".startsWith("te")); log("test".endsWith("st")); log("test".indexOf("e")); let x = ["a", "b"]; log(x.join("-")); log("foo".replace("o", "0")); log("foo".replaceAll("o", "0")); log(Json.stringify(("a-b-c-d-e".split("-")))); log("TEST".lowercase()); log("test".uppercase());

在本地通过 Wing 控制台运行(wing it),预期输出:

true 4 true true 1 a-b f0o f00 ["a","b","c","d","e"] test TEST

注意上例中"test".indexOf("e")返回1(首个e的位置),以及split("-")的结果经Json.stringify输出为 JSON 数组形式。

七、源码视角:@macro与 JS 原生方法的映射

从 packages/@winglang/sdk/src/std/string.ts 可以看到,String类的大多数实例方法并非真正实现,而是通过 JSDoc 中的@macro指令在编译期展开为 JavaScript 原生字符串方法,形成一个轻量、无运行时开销的映射层:

Wing 方法编译期展开为(JS)
at带越界检查的自定义展开(见 3.1)
contains$self$.includes($args$)
endsWith$self$.endsWith($args$)
indexOf$self$.indexOf($args$)
lowercase$self$.toLocaleLowerCase()
uppercase$self$.toLocaleUpperCase()
replace$self$.replace(...$args$)
replaceAll$self$.replaceAll(...$args$)

这一点解释了contains与indexOf的大小写敏感行为、indexOf未命中返回-1、replace只替换首处等语义,均与 JS 原生String对象保持一致。源码注释同时说明:该类的目的是为 Wing 编译器提供str类型的 JSII 子集,通常不应被用户直接实例化消费。

八、方法速查总表

以下为 docs/api/04-standard-library/std/string.md 中定义的完整 API 一览:

类别名称签名说明
属性lengthlength: num字符串长度
查询containscontains(searchString: str): bool是否包含子串(大小写敏感)
查询startsWithstartsWith(searchString: str): bool是否以子串开头
查询endsWithendsWith(searchString: str): bool是否以子串结尾
查询indexOfindexOf(searchString: str): num首次出现索引,未找到返回 -1
提取atat(index: num): str取指定索引字符,支持负索引,越界抛错
提取substringsubstring(indexStart: num, indexEnd?: num): str截取子串,结束索引可选
变换replacereplace(searchString: str, replaceString: str): str替换首次出现的子串
变换replaceAllreplaceAll(searchString: str, replaceString: str): str替换全部出现的子串
变换lowercaselowercase(): str转为小写(本地化规则)
变换uppercaseuppercase(): str转为大写(本地化规则)
变换trimtrim(): str移除首尾空白
变换concatconcat(strN: str): str拼接字符串
变换splitsplit(separator: str): MutArray<str>按分隔符拆分(空串按字符拆)
静态fromJsonstr.fromJson(json: Json, options?: JsonValidationOptions): str从Json安全转换并校验

延伸阅读

  • API 参考原文:docs/api/04-standard-library/std/string.md
  • 实战示例与输出:docs/by-example/21-string-functions.md
  • 语言参考(str类型与字符串字面量、fromJson校验模型):docs/api/05-language-reference.md
  • 标准库源码实现(String类与@macro):packages/@winglang/sdk/src/std/string.ts
  • 校验选项定义(JsonValidationOptions.unsafe):packages/@winglang/sdk/src/std/json.ts
  • SDK 测试套件(覆盖全部方法与边界行为):tests/sdk_tests/std/string.test.w
  • 语言级字符串语义测试:tests/valid/std_string.test.w
  • 编程语言
  • 编译器
  • 云原生
  • 语言运行时

【免费下载链接】wing

A programming language for the cloud ☁️ A unified programming model, combining infrastructure and runtime code into one language ⚡

项目地址:https://gitcode.com/gh_mirrors/wi/wing
点击查看免费下载

相关推荐

上一篇:AutoMapper 继承映射(Mapping Inheritance)完整指南:配置继承、运行时多态与优先级机制
下一篇:字符串操作增强插件:StringManipulation深度解读

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/13 1:39:33

MAS 激活器:三步免费永久激活 Windows 11 与 Office

MAS 激活器&#xff1a;三步免费永久激活 Windows 11 与 Office 【免费下载链接】Microsoft-Activation-Scripts Open-source Windows and Office activator featuring HWID, Ohook, TSforge, and Online KMS activation methods, along with advanced troubleshooting. 项目…

作者头像 李华
网站建设 2026/10/13 1:38:32

java项目实战滑雪场管理系统[文档+开题+PPT

&#x1f345;选题推荐——以防找不到我们&#xff0c;点击上方订阅专栏✌✌\ Java毕设实战项目 Python毕设项目源代码 asp.net毕业设计项目 Uniapp安卓毕业设计项目 node.js毕业设计项目 python毕业设计 微信小程序毕业设计项目 php毕业设计 &#x1f447;&#x1f3fb;&#…

作者头像 李华
网站建设 2026/10/13 1:38:29

AI 时代的:一个老程序员的转型、困境与自白

一、我曾经的"黄金时代"作为一个写了二十多年代码的传统程序员&#xff0c;我至今怀念以前的工作模式。那时候&#xff0c;一个性能问题、一个 bug、甚至一个莫名其妙的坑&#xff0c;常常让我在代码里兜兜转转几天、几个星期。但解决之后那种满满的成就感&#xff0…

作者头像 李华