华为仓颉语言介绍
文章目录
- 1.简介
- 2.初识仓颉语言
- 3.基本概念
- 3.1标识符
- 3.2程序结构
- 3.3变量
- 3.4表达式
- 3.4.1if 表达式
- 3.4.2while语句
- 3.4.3do-while表达式
- 3.4.4 for-in 表达式
- 3.4.5 where条件
- 3.4.6 break和continue
- 3.5 函数
1.简介
随着万物互联以及智能时代的到来,软件的形态将发生巨大的变化。一方面,移动应用和移动互联网领域仍然强力驱动人机交互、设备协同、智能化、安全性等方向的创新,另一方面人工智能也同样驱动软件朝智能化、端边云协同等方向演进。新技术、新场景下应用软件的开发对编程语言提出了新的诉求和挑战。
仓颉编程语言作为一款面向全场景应用开发的现代编程语言,通过现代语言特性的集成、全方位的编译优化和运行时实现、以及开箱即用的IDE工具链支持,为开发者打造友好开发体验和卓越程序性能。其具体特性表现为:
-
高效编程:面向应用开发,我们希望语言能够易学易用,降低开发者入门门槛和开发过程中的心智负担,支持各种常见的开发范式和编程模式,让开发者简洁高效地表达各种业务逻辑。仓颉是一门多范式编程语言,支持函数式、命令式和面向对象等多种范式,包括值类型、类和接口、泛型、代数数据类型、模式匹配、以及高阶函数等特性。此外,仓颉还支持类型推断,能够降低开发者类型标注的负担;通过一系列简明高效的语法,能够减少冗余书写、提升开发效率;语言内置的各种语法糖和宏(macro)的能力,支持开发者基于仓颉快速开发领域专用语言(DSL),构建领域抽象。
-
安全可靠:作为现代编程语言,仓颉追求编码即安全,通过静态类型系统和自动内存管理,确保程序的类型安全和null safety等内存安全;同时,仓颉还提供各种运行时检查,包括数组下标越界检查、类型转换检查、数值计算溢出检查、以及字符串编码合法性检查等,能够及时发现程序运行中的错误;此外,还通过代码扫描工具、混淆工具以及消毒器,进一步提供跨语言互操作安全和代码资产保护等支持。
-
轻松并发:并发和异步编程能够有效提高处理器利用率,并在交互式应用中确保程序的响应速度,是应用开发中必不可少的能力。仓颉语言实现了轻量化用户态线程和并发对象库,让高效并发变得轻松。
仓颉语言采用用户态线程模型,每个仓颉线程都是极其轻量级的执行实体,拥有独立的执行上下文但共享内存。对开发者来说,用户态线程的使用和传统的系统线程的使用方式保持一致,没有带来额外负担;而从运行态视角看,线程的管理由运行时完成,不依赖操作系统的线程管理,因此线程的创建、调度和销毁等操作更加高效,且资源占用比系统线程更少。为了避免数据竞争,仓颉语言提供了并发对象库,并发对象的方法是线程安全的,因此在多线程中调用这些方法和串行编程没有区别,应用逻辑的开发者无需额外关心并发管理。对于一些核心库,仓颉还提供了无锁或者细粒度锁的算法实现,能够进一步减少线程的阻塞,提升并发度。
-
卓越性能:仓颉编译器及运行时从全栈对编译进行优化,包括编译器前端基于CHIR(Cangjie HighLevel IR)高层编译优化(比如语义感知的循环优化、语义感知的后端协同优化等),基于后端的编译优化(比如:SLP向量化、Intrinsic优化、InlineCache、过程间指针优化、Barrier优化等),基于运行时的优化(比如轻量锁、分布式标记、并发Tracing优化等),一系列的优化让仓颉充分发挥处理器能力,为应用提供卓越的性能支持。另外仓颉语言对运行时进行原生的轻量化设计,通过对运行时模块化分层设计,定义仓颉公共对象模型和运行时公共基础组件,基于公共对象模型,实现运行时的内存管理、回栈、异常处理、跨语言调用等基础能力,大幅减少多个能力间的冗余对象设计,精简运行时体积。同时通过包的按需加载技术,减少仓颉应用启动的冗余包内存开销,因此对于资源敏感设备,占用资源更少,支持更友好。
除此之外,仓颉还支持面向应用开发的一系列工具链,包括语言服务(高亮、联想)、调试(跨语言调试、线程级可视化调试)、静态检查、性能分析、包管理、文档生成、Mock工具、测试框架、覆盖率工具、Fuzz工具以及智能辅助编程工具,进一步提升软件开发体验以及效率。
2.初识仓颉语言
仓颉编程语言是一种面向全场景应用开发的通用编程语言,可以兼顾开发效率和运行性能,并提供良好的编程体验,主要具有如下特点:
- 语法简明高效:仓颉编程语言提供了一系列简明高效的语法,旨在减少冗余书写、提升开发效率,例如插值字符串、主构造函数、Flow 表达式、match、if-let、while-let 和重导出等语法,让开发者可以用较少编码表达相关逻辑。
- 多范式编程:仓颉编程语言支持函数式、命令式和面向对象等多范式编程,融合了高阶函数、代数数据类型、模式匹配、泛型等函数式语言的先进特性,还有封装、接口、继承、子类型多态等支持模块化开发的面向对象语言特性,以及值类型、全局函数等简洁高效的命令式语言特性。开发者可以根据开发偏好或应用场景,选用不同的编程范式。
- 类型安全:仓颉编程语言是静态强类型语言,通过编译时类型检查尽早识别程序错误,降低运行时风险,也便于代码维护。同时,仓颉编译器提供了强大的类型推断能力,可以减少类型标注工作,提高开发效率。
- 内存安全:仓颉编程语言支持自动内存管理,并在运行时进行数组下标越界检查、溢出检查等,确保运行时内存安全。
- 高效并发:仓颉编程语言提供了用户态轻量化线程(原生协程),以及简单易用的并发编程机制,保证并发场景的高效开发和运行。
- 兼容语言生态:仓颉编程语言支持和 C 等主流编程语言的互操作,并采用便捷的声明式编程范式,可实现对其他语言库的高效复用和生态兼容。
- 领域易扩展:仓颉编程语言提供了基于词法宏的元编程能力,支持在编译时变换代码,此外,还提供了尾随 lambda、属性、操作符重载、部分关键字可省略等特性,开发者可由此深度定制程序的语法和语义,有利于内嵌式领域专用语言(Embedded Domain Specific Languages,EDSL)的构建。
- 助力 UI 开发:UI 开发是构建端侧应用的重要环节,基于仓颉编程语言的元编程和尾随 lambda 等特性,可以搭建声明式 UI 开发框架,提升 UI 开发效率和体验。
- 内置库功能丰富:仓颉编程语言提供了功能丰富的内置库,涉及数据结构、常用算法、数学计算、正则匹配、系统交互、文件操作、网络通信、数据库访问、日志打印、解压缩、编解码、加解密和序列化等功能。
3.基本概念
3.1标识符
在仓颉编程语言中,开发者可以给一些程序元素命名,这些名字也被称为“标识符”,标识符分为普通标识符和原始标识符两类,它们分别遵从不同的命名规则。
普通标识符不能和仓颉关键字相同,可以取自以下两类字符序列:
- 由英文字母开头,后接零至多个英文字母、数字或下划线“_”。
- 由一至多个下划线“_”开头,后接一个英文字母,最后可接零至多个英文字母、数字或下划线。
例如
//以下每行字符串都是合法的普通标识符:
abc
_abc
abc_
a1b2c3
a_b_c
a1_b2_c3//以下每行字符串都是不合法的普通标识符:
ab&c // 使用了非法字符 “&”
_123 // 起始下划线 “_” 后不能接数字
3abc // 数字不能出现在头部
while // 不能使用仓颉关键字
原始标识符是在普通标识符或仓颉关键字的外面加上一对反引号,主要用于将仓颉关键字作为标识符的场景。
//以下每行字符串都是合法的原始标识符
`abc`
`_abc`
`a1b2c3`
`if`
`while`//以下每行字符串,由于反引号内的部分是不合法的普通标识符,所以它们整体也是不合法的原始标识符
`ab&c`
`_123`
`3abc`
3.2程序结构
通常,我们都会在扩展名为 .cj 的文本文件中编写仓颉程序,这些程序和文件也被称为源代码和源文件,在程序开发的最后阶段,这些源代码将被编译为特定格式的二进制文件。
在仓颉程序的顶层作用域中,可以定义一系列的变量、函数和自定义类型(如 struct、class、enum 和 interface 等),其中的变量和函数分别被称为全局变量和全局函数。如果要将仓颉程序编译为可执行文件,您需要在顶层作用域中定义一个 main 函数作为程序入口,它可以有 Array 类型的参数,也可以没有参数,它的返回值类型可以是整数类型或 Unit 类型。
例如在以下程序中,我们在顶层作用域定义了全局变量 a 和全局函数 b,还有自定义类型 C、D 和 E,以及作为程序入口的 main 函数。
// example.cj
let a = 2023
func b() {}
struct C {}
class D {}
enum E { F | G }main() {println(a)
}
在非顶层作用域中不能定义上述自定义类型,但可以定义变量和函数,称之为局部变量和局部函数。特别地,对于定义在自定义类型中的变量和函数,称之为成员变量和成员函数。
// example.cj
func a() {let b = 2023func c() {println(b)}c()
}class A {let b = 2024public func c() {println(b)}
}main() {a()A().c()
}
3.3变量
在仓颉编程语言中,一个变量由对应的变量名、数据(值)和若干属性构成,开发者通过变量名访问变量对应的数据,但访问操作需要遵从相关属性的约束(如数据类型、可变性和可见性等)。
变量定义的具体形式为:
修饰符 变量名: 变量类型 = 初始值
其中修饰符用于设置变量的各类属性,可以有一个或多个,常用的修饰符包括:
- 可变性修饰符:let 与 var,分别对应不可变和可变属性,可变性决定了变量被初始化后其值还能否改变,仓颉变量也由此分为不可变变量和可变变量两类。
- 可见性修饰符:private 与 public 等,影响全局变量和成员变量的可引用范围,详见后续章节的相关介绍。
- 静态性修饰符:static,影响成员变量的存储和引用方式,详见后续章节的相关介绍。
在定义仓颉变量时,可变性修饰符是必要的,在此基础上,还可以根据需要添加其他修饰符。
-
变量名应是一个合法的仓颉标识符。
-
变量类型指定了变量所持有数据的类型。当初始值具有明确类型时,可以省略变量类型标注,此时编译器可以自动推断出变量类型。
-
初始值是一个仓颉表达式,用于初始化变量,如果标注了变量类型,需要保证初始值类型和变量类型一致。在定义全局变量或静态成员变量时,必须指定初始值。在定义局部变量或实例成员变量时,可以省略初始值,但需要标注变量类型,同时要在此变量被引用前完成初始化,否则编译会报错。
例如,下列程序定义了两个 Int64 类型的不可变变量 a 和可变变量 b,随后修改了变量 b 的值,并调用 println 函数打印 a 与 b 的值。
main() {let a: Int64 = 20var b: Int64 = 12b = 23println("${a}${b}")
}
3.4表达式
在一些传统编程语言中,一个表达式由一个或多个操作数(operand)通过零个或多个操作符(operator)组合而成,表达式总是隐含着一个计算过程,因此每个表达式都会有一个计算结果,对于只有操作数而没有操作符的表达式,其计算结果就是操作数自身,对于包含操作符的表达式,计算结果是对操作数执行操作符定义的计算而得到的值。在这种定义下的表达式也被称为算术运算表达式。
在仓颉编程语言中,我们简化并延伸了表达式的传统定义——凡是可求值的语言元素都是表达式。因此,仓颉不仅有传统的算术运算表达式,还有条件表达式、循环表达式和 try 表达式等,它们都可以被求值,并作为值去使用,如作为变量定义的初值和函数实参等。此外,因为仓颉是强类型的编程语言,所以仓颉表达式不仅可求值,还有确定的类型。
仓颉编程语言的各种表达式将在后续章节中逐一介绍,本节介绍最常用的条件表达式、循环表达式以及部分控制转移表达式(break、continue)。
我们知道,任何一段程序的执行流程,只会涉及三种基本结构——顺序结构、分支结构和循环结构。实际上,分支结构和循环结构,是由某些指令控制当前顺序执行流产生跳转而得到的,它们让程序能够表达更复杂的逻辑,在仓颉中,这种用来控制执行流的语言元素就是条件表达式和循环表达式。
在仓颉编程语言中,条件表达式分为 if 表达式和 if-let 表达式两种,它们的值与类型需要根据使用场景来确定。循环表达式有四种:for-in 表达式、while 表达式、do-while 表达式和 while-let 表达式,它们的类型都是 Unit、值为 ()。其中 if-let 表达式和 while-let 表达式都与模式匹配相关,请参见if-let 表达式和while-let 表达式章节,本节只介绍以上提及的其他几种表达式。
在仓颉程序中,由一对大括号“{}”包围起来的一组表达式,被称为“代码块”,它将作为程序的一个顺序执行流,其中的表达式将按编码顺序依次执行。如果代码块中有至少一个表达式,我们规定此代码块的值与类型等于其中最后一个表达式的值与类型,如果代码块中没有表达式,规定这种空代码块的类型为 Unit、值为 ()。
3.4.1if 表达式
if 表达式的基本形式为
if (条件) {分支 1
} else {分支 2
}
其中“条件”是布尔类型表达式,“分支 1”和“分支 2”是两个代码块。if 表达式将按如下规则执行:
- 计算“条件”表达式,如果值为 true 则转到第 2 步,值为 false 则转到第 3 步。
- 执行“分支 1”,转到第 4 步。
- 执行“分支 2”,转到第 4 步。
- 继续执行 if 表达式后面的代码。
在一些场景中,我们可能只关注条件成立时该做些什么,所以 else 和对应的代码块是允许省略的。
如下程序演示了 if 表达式的基本用法:
import std.random.*
main() {let number: Int8 = Random().nextInt8()println(number)if (number % 2 == 0) {println("偶数")} else {println("奇数")}
}
3.4.2while语句
while 表达式的基本形式为
while (条件) {循环体
}
其中“条件”是布尔类型表达式,“循环体”是一个代码块。while 表达式将按如下规则执行:
- 计算“条件”表达式,如果值为 true 则转第 2 步,值为 false 转第 3 步。
- 执行“循环体”,转第 1 步。
- 结束循环,继续执行 while 表达式后面的代码。
例如,以下程序使用 while 表达式,基于二分法,近似计算数字 2 的平方根:
main() {var root = 0.0var min = 1.0var max = 2.0var error = 1.0let tolerance = 0.1 ** 10while (error ** 2 > tolerance) {root = (min + max) / 2.0error = root ** 2 - 2.0if (error > 0.0) {max = root} else {min = root}}println("2 的平方根约等于:${root}")
}
3.4.3do-while表达式
do-while 表达式的基本形式为:
do {循环体
} while (条件)
其中“条件”是布尔类型表达式,“循环体”是一个代码块。do-while 表达式将按如下规则执行:
- 执行“循环体”,转第 2 步。
- 计算“条件”表达式,如果值为 true 则转第 1 步,值为 false 转第 3 步。
- 结束循环,继续执行 do-while 表达式后面的代码。
例如,以下程序使用 do-while 表达式,基于蒙特卡洛算法,近似计算圆周率的值:
import std.random.*main() {let random = Random()var totalPoints = 0var hitPoints = 0do {// 在 ((0, 0), (1, 1)) 这个正方形中随机取点let x = random.nextFloat64()let y = random.nextFloat64()// 判断是否落在正方形内接圆里if ((x - 0.5) ** 2 + (y - 0.5) ** 2 < 0.25) {hitPoints++}totalPoints++} while (totalPoints < 1000000)let pi = 4.0 * Float64(hitPoints) / Float64(totalPoints)println("圆周率近似值为:${pi}")
}
3.4.4 for-in 表达式
for-in 表达式可以遍历那些扩展了迭代器接口 Iterable 的类型实例。for-in 表达式的基本形式为:
for (迭代变量 in 序列) {循环体
}
其中“循环体”是一个代码块。“迭代变量”是单个标识符或由多个标识符构成的元组,用于绑定每轮遍历中由迭代器指向的数据,可以作为“循环体”中的局部变量使用。“序列”是一个表达式,它只会被计算一次,遍历是针对此表达式的值进行的,其类型必须扩展了迭代器接口 Iterable。for-in 表达式将按如下规则执行:
- 计算“序列”表达式,将其值作为遍历对象,并初始化遍历对象的迭代器。
- 更新迭代器,如果迭代器终止,转第 4 步,否则转第 3 步。
- 将当前迭代器指向的数据与“迭代变量”绑定,并执行“循环体”,转第 2 步。
- 结束循环,继续执行 for-in 表达式后面的代码。
例如,以下程序使用 for-in 表达式,遍历中国地支字符构成的数组 noumenonArray,输出农历 2024 年各月的干支纪法:
main() {let metaArray = [r'甲', r'乙', r'丙', r'丁', r'戊',r'己', r'庚', r'辛', r'壬', r'癸']let noumenonArray = [r'寅', r'卯', r'辰', r'巳', r'午', r'未',r'申', r'酉', r'戌', r'亥', r'子', r'丑']let year = 2024// 年份对应的天干索引let metaOfYear = ((year % 10) + 10 - 4) % 10// 此年首月对应的天干索引var index = (2 * metaOfYear + 3) % 10 - 1println("农历 2024 年各月干支:")for (noumenon in noumenonArray) {print("${metaArray[index]}${noumenon} ")index = (index + 1) % 10}
}
3.4.5 where条件
在部分循环遍历场景中,对于特定取值的迭代变量,我们可能需要直接跳过、进入下一轮循环,虽然可以使用 if 表达式和 continue 表达式在循环体中实现这一逻辑,但仓颉为此提供了更便捷的表达方式——可以在所遍历的“序列”之后用 where 关键字引导一个布尔表达式,这样在每次将进入循环体执行前,会先计算此表达式,如果值为 true 则执行循环体,反之直接进入下一轮循环。例如:
main() {for (i in 0..8 where i % 2 == 1) { // i 为奇数才会执行循环体println(i)}
}
3.4.6 break和continue
在循环结构的程序中,有时我们需要根据特定条件提前结束循环或跳过本轮循环,为此仓颉引入了 break 与 continue 表达式,它们可以出现在循环表达式的循环体中,break 用于终止当前循环表达式的执行、转去执行循环表达式之后的代码,continue 用于提前结束本轮循环、进入下一轮循环。break 与 continue 表达式的类型都是 Nothing。
例如,以下程序使用 for-in 表达式和 break 表达式,在给定的整数数组中,找到第一个能被 5 整除的数字:
main() {let numbers = [12, 18, 25, 36, 49, 55]for (number in numbers) {if (number % 5 == 0) {println(number)break}}
}
以下程序使用 for-in 表达式和 continue 表达式,将给定整数数组中的奇数打印出来:
main() {let numbers = [12, 18, 25, 36, 49, 55]for (number in numbers) {if (number % 2 == 0) {continue}println(number)}
}
3.5 函数
仓颉使用关键字 func 来表示函数定义的开始,func 之后依次是函数名、参数列表、可选的函数返回值类型、函数体。其中,函数名可以是任意的合法标识符,参数列表定义在一对圆括号内(多个参数间使用逗号分隔),参数列表和函数返回值类型(如果存在)之间使用冒号分隔,函数体定义在一对花括号内。
函数定义举例:
func add(a: Int64, b: Int64): Int64 {return a + b
}
上例中定义了一个名为 add 的函数,其参数列表由两个 Int64 类型的参数 a 和 b 组成,函数返回值类型为 Int64,函数体中将 a 和 b 相加并返回。
相关文章:
华为仓颉语言介绍
文章目录 1.简介2.初识仓颉语言3.基本概念3.1标识符3.2程序结构3.3变量3.4表达式3.4.1if 表达式3.4.2while语句3.4.3do-while表达式3.4.4 for-in 表达式3.4.5 where条件3.4.6 break和continue 3.5 函数 1.简介 随着万物互联以及智能时代的到来,软件的形态将发生巨大…...
《昇思 25 天学习打卡营第 3 天 | 张量 Tensor 》
《昇思 25 天学习打卡营第 3 天 | 张量 Tensor 》 活动地址:https://xihe.mindspore.cn/events/mindspore-training-camp 签名:Sam9029 感觉像是在 学习高数一样 张量 Tensor 张量是一种特殊的数据结构,与数组和矩阵非常相似。 张量…...
free命令——显示系统内存使用情况
free命令的功能是显示系统内存使用情况,包含物理内存和交换内存的总量、使用量和空闲量。 语法格式:free [选项] 常用选项及含义 选项含义-b以字节B为单位显示内存和交换内存的容量使用情况-k以KB为单位显示内存和交换内存的容量使用情况-m以MB为单位…...

麒麟移动运行环境(KMRE)——国内首个开源的商用移固融合“Android生态兼容环境”正式开源
近日,由麒麟软件研发的KMRE(Kylin Mobile Runtime Environment,麒麟移动运行环境)在openKylin(开放麒麟)社区正式发布,为Linux桌面操作系统产品提供了高效的Android运行环境解决方案。这也是国内…...
print(“{}{}“.format())
print("{}{}".format()) 是 Python 中用于格式化字符串并将其输出到控制台的一种方法。format 方法允许你在字符串中插入变量或表达式的值,并以指定的格式显示它们。 基本语法 print("format_string".format(value1, value2, ...))format_str…...

2-12 基于CV模型卡尔曼滤波、CT模型卡尔曼滤波、IMM模型滤波的目标跟踪
基于CV模型卡尔曼滤波、CT模型卡尔曼滤波、IMM模型滤波的目标跟踪。输出跟踪轨迹及其误差。程序已调通,可直接运行。 2-12 CV模型卡尔曼滤波 CT模型卡尔曼滤波 - 小红书 (xiaohongshu.com)...
序列1bp插入有什么影响
1bp插入突变(1个碱基插入)在基因序列中通常会引起以下几种影响: 移码突变(Frameshift Mutation): 插入的一个碱基会改变插入点之后所有的密码子,导致读取框的移动。这种变化通常会引起整个蛋白质…...

CVPR 2024盛况空前,上海科技大学夺得最佳学生论文奖,惊艳全场
CVPR 2024盛况空前!上海科技大学夺得最佳学生论文奖,惊艳全场! 会议之眼 快讯 2024 年 CVPR (Computer Vision and Pattern Recogntion Conference) 即国际计算机视觉与模式识别会议,于6月17日至21日正在美国西雅图召…...

HTTP 状态码详解及使用场景
目录 1xx 信息性状态码2xx 成功状态码3xx 重定向状态码4xx 客户端错误状态码5xx 服务器错误状态码 HTTP思维导图连接:https://note.youdao.com/s/A7QHimm0 1xx 信息性状态码 100 Continue:表示客户端应继续发送请求的其余部分。 使用场景:客…...

【Windows】配置Flutter开发环境
一、下载 flutter sdk 点此跳至下载官网 下载好flutter sdk,并解压到自定义的位置。 二、配置环境变量 此电脑 --> 右键 选择 属性 --> 点击 高级系统设置 --> 会弹出系统属性的窗口,点击 环境变量 按钮 1.配置加速镜像地址 PUB_HOSTED_…...

云渲染与传统渲染器的较量与融合
随着云计算技术的突破性进展,云渲染技术应运而生,为传统渲染器带来了前所未有的挑战与机遇。云渲染,以其在计算资源、可扩展性、协作便利性等方面的显著优势,正在重新定义渲染行业的标准。云渲染与传统渲染器之间的核心差异&#…...
比较新旧两数组列表,新增或删除数据库记录(ai生成)
两数组比较 元素相同则不处理,缺少则删除数据库记录,多余则新增数据库记录。 为了解决这个问题,我们需要定义两个数组array1和array2,它们包含数据库中的记录。然后,我们可以遍历这两个数组,并对数据库执行相应的操作。以下是一个…...

Java基础 - 练习(五)根据今天日期获取一周内的日期(基姆拉尔森公式)
基姆拉尔森计算公式用于计算一周内的日期。比如给你年月日,从而计算今天是星期几。 基姆拉尔森公式 Week (d2*m3*(m1)/5yy/4-y/100y/4001) mod 7, 3<m<14Week的取值范围是0 ~ 6,其中0代表星期日,1 ~ 6分别代表星期一到星期…...
HTML5 新元素
HTML5 新元素 HTML5是最新版本的HTML,引入了许多新元素和功能,以更好地满足现代网页设计的需要。这些新元素不仅增强了网页的表现力,还提高了代码的可读性和可维护性。本文将详细介绍HTML5中的新元素,包括它们的功能和用法。 1.…...

虹软ArcSoft—真正离线免费的人脸识别SDK
虹软ArcSoft—真正离线免费的人脸识别SDK 高级功能收费 还是很好滴 人证核验功能是C/C的SDK,需要封装为C#,然后暴露为Restful API使用...

[环境配置]vscode通过ssh连接autodl进行项目开发
警告:如果使用VSCode直接执行或开终端执行训练程序,请在调试完成后最后通过screen/tmux工具开守护进程,确保程序不受SSH连接中断影响程序执行! 官方文档:请戳 AutoDL使用方法: 在进行操作前您需要提前安装…...

2024中国宁波-东南亚职业教育产教协同发展校企对接会举办
2024年6月16日,由东南亚教育部长组织技术教育发展中心(SEAMEO TED)、联合国教科文组织国际农村教育研究与培训中心(UNESCO INRULED)、中国教育国际交流协会(CEAIE)三方主办的“2024中国宁波-东南…...
Web前端、后端与建站:全方位解析四大基石、五大挑战、六大技术与七大策略
Web前端、后端与建站:全方位解析四大基石、五大挑战、六大技术与七大策略 在当今数字化时代,Web前端、后端以及建站技术已经成为构建现代网站和应用不可或缺的关键要素。本文将从四个方面探讨Web前端与后端的基础,从五个方面分析建站过程中的…...

nginx出现504 Gateway Time-out错误的原因分析及解决
nginx出现504 Gateway Time-out错误的原因分析及解决 1、查看公网带宽是否被打满 2、查看网络是否有波动(可以在nginx上ping后端服务,看是否有丢包情况) 3、查看服务器资源使用情况(cpu、内存、磁盘、网络等) 4、查看nginx日志,具体到哪个服务的哪个…...

基于STM32的智能插座项目
本项目基于stm32f103c8t6芯片通过集成众多模块和元器件,通过ESP01-S和阿里云平台实现智能插座的项目开展。资料获取到咸🐟:xy591215295250 \\\或者联系wechat 号:comprehensivable 随着电子科学与技术的快速发展,软硬件…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...