在前端名目中经常使用Rust-编译为-WebAssembly (前端name)
前言
最近,不是放大了对关系文章的输入吗,在评论区或许私信区。有一些不同的声响说:Rust没有出路,而后...."。其实呢,看一个技术能否有须要学习的能源。想必大家的底层理由都是「一切都是向钱看」,毕竟在国际大家都是业务为主,想自己纯手搞一套合乎自己的技术框架和范式,这是不实际践的。(当然也不能一杆子打死,还是有很多技术大牛的)如今大家纠结或许对这个技术属于张望态度,无非就是在往常开发上班中没有触及到的点。
同时,由于国际技术的「滞后性」,有一些运行场景其实还是处于蛮荒的形态。(不是崇洋媚外,理想确实如此)。所以,在一些可以用到新的技术点的方向上,国际还是处于蓝海阶段。
所以,本着对该技术的独无关注度,我还是选用义无反顾的投身到学习和实践中。「突破黎明之前的光明,你会领有太阳,而晨光中第一缕阳光也是为你而夺目」。
图片
而详细,Rust究竟能给你带来点啥,咱们之前有文章讲过,这里就不在赘述了。
Lastbutnotleaset,由于如今自己临时专一于前端畛域居多,所以我更多关注Rust能为前端带来点啥。而说到Rust和前端,第一点的联想就是:WebAssembly。(假设,不了解何为WebAssembly,可以参考咱们之前的文章阅读器第四种言语-WebAssembly,外面的例子是用Emscripten写的)
其实,咱们之前写过如何用C写wasm,也写过WebAssembly-C与JS相互操作等文章。但是,由于一些无法言喻的要素放置了。
咱们当天将经常使用Rust创立一个WebAssemblyHelloWorld程序。咱们将深化了解由wasm-bindgen生成的代码,以及它们如何独特单干来协助咱们启动开发。咱们还将经常使用wabt来探求生成的wasm代码。这将使咱们更好地理解RustWebAssembly,并为咱们的开发奠定良好的基础。
好了,天不早了,干点正事哇。
咱们能所学到的常识点
1.前置常识点
「前置常识点」,只是做一个概念的引见,不会做深度解释。由于,这些概念在上方文章中会有出现,为了让行文愈加的顺畅,所以将本该在文内的概念解监禁到前面来。「假设大家对这些概念相熟,可以间接疏忽」同时,由于阅读我文章的个体有很多,所以有些常识点或许「我视之若珍宝,尔视只如草芥,弃之如敝履」。以下常识点,请「酌情经常使用」。
装置Rust
假设是你一个Rust萌新,咱们也给你提供Rust环境性能和入门指南。
假设,想独立成功装置,可以到Rust装置页面跟着教程装置。
在装置成功Rust后,它会装置一个名为rustup的工具,这个工具能让咱们治理多个不同版本的Rust。自动状况下,它会装置用于惯常Rust开发的stable版本RustRelease。
Rustup会装置
由于,我本机曾经装置好了Rust。咱们可以经过rustup--version来检查rustup的版本。以下是我本机的rustup版本信息。下文中一切的代码,都基于该版本。
rustup--versionrustup1.26.0(5af9b94842023-04-05)
![编译为](https://tyye.cn/zb_users/theme/tpure/style/images/lazyload.png)
装置WebAssembly二进制工具包(wabt)
图片
这些工具旨在用于开发工具链或其余系统,这些系统宿愿「操作WebAssembly文件」。与WebAssembly规范解释器不同(该解释器旨在尽或许便捷、申明性和规范性),这些工具是用C/C++编写的,并设计成更容易集成到其余系统中。这些工具不旨在提供提升平台或更初级的编译指标;同样,它们旨在成功与规范的齐全顺应和听从。
咱们可以应用brew来在环境下装置。
图片
2.名目搭建
2.1装置wasm-bindgen
咱们可以经过cargoinstall--list来检查在$HOME/.cargo/bin位置装置过的Rust二进制文件。
在一些其余的教程中可以不经常使用wasm-bindgen构建HelloWorld程序,但是在本文中,咱们将经常使用它,由于它在RustWebAssembly开发中是必无法少的。
cargoinstallwasm-bindgen-cli
RustWebAssembly准许咱们将WebAssembly模块有针对性地拔出到现有的Script运行程序中,尤其是在「性能关键的代码门路」中。咱们可以将wasm-bindgen视为一种工具,它经过生成用于JavaScript和WebAssembly之间高效交互的「粘合代码」和绑定来协助咱们成功丝滑的交互体验。
2.2创立RustWebAssembly名目
巴拉拉小魔仙,念诵如下咒语,构建一个RustWebAssembly名目。
cargonewhello_world--lib
上方的代码是经常使用Cargo工具创立一个新的Rust名目,名目的称号是hello_world,并且指定它是一个库(--lib)。这将创立一个蕴含基本名目结构的文件夹,其中包括一个Cargo.toml文件和一个src文件夹。
+--Cargo.toml+--src+--lib.rs
2.3修正Cargo.toml性能项
经常使用宇宙最强IDE-VScode,关上Cargo.toml文件。咱们应该会看到以下内容。
[package]name="hello_world"version="0.1.0"authors=["789"]edition="2021"[dependencies]
将其修正成上方的内容
[package]name="hello_world"version="0.1.0"authors=["789"]edition="2021"[lib]crate-type=["cdylib"][dependencies]wasm-bindgen="0.2"
上方的大局部字段大家都能看懂,其中lib项的性能,这里稍微解释一下:
crate-type=["cdylib"]:这一行「指定了生成的库的类型」。在这里,crate-type设置为["cdylib"],这示意咱们正在创立一个灵活链接库(C-compatibledynamiclibrary)。这用于编译一个供其余编程言语加载的灵活库。此输入类型将在上创立*.so文件,在macOS上创立*.dylib文件,在上创立*.dll文件。
这种类型的库可以被其余编程言语调用,由于它们与C言语兼容。这关于与WebAssembly(Wasm)互操作性很关键,由于Wasm理论须要与C言语接口启动交互。因此,cdylib示意该库是一个可供其余言语经常使用的灵活链接库。
2.4编辑lib.rs
关上src/lib.rs文件。将其更改为以下内容:
externcratewasm_bindgen;usewasm_bindgen::prelude::*;//导入'window.alert'#[wasm_bindgen]extern"C"{fnalert(s:&str);}//导出一个'helloworld'函数#[wasm_bindgen]pubfnhelloworld(name:&str){alert(&format!("HelloWorld:{}!",name));}
咱们便捷解释一下外围代码:
在Rust中调用来自JavaScript的外部函数
#[wasm_bindgen]extern"C"{fnalert(s:&str);}
#[wasm_bindgen]:在#[]中的内容叫做"属性",并以某种形式扭转上方的语句。#[wasm_bindgen]是一个「属性标志」,用于指定与WebAssembly互操作关系的个性。
extern"C"{fnalert(s:&str);}:这里申明了一个「外部函数」alert,它经常使用extern"C"指定了CABI(运行二进制接口),这象征着它「可以与C言语启动交互」。「这个alert函数没有在Rust中成功,而是在JavaScript中成功,用于在阅读器中显示正告框」。
在JavaScript中调用的Rust函数
#[wasm_bindgen]pubfnhelloworld(name:&str){alert(&format!("HelloWorld:{}!",name));}
#[wasm_bindgen]pubfnhelloworld(name:&str):这是一个Rust函数helloworld,它被标志为wasm_bindgen,这象征着它「可以被JavaScript调用」。这个函数接受一个「字符串参数」name,而后调用「之前申明」的alert函数,以显示带有HelloWorld信息的弹框,并在信息中包括name参数的内容。
2.5编译代码
在命令行中输入以下命令:
cargobuild--targetwasm32-unknown-unknown
假设未装置对应的库,控制台会给出揭示。
图片
那咱们就照猫画虎的操作一下:
rustuptargetaddwasm32-unknown-unknown❞
当运转这个命令后,Cargo会经常使用Rust编译器(Rustc)以及与WebAssembly关系的工具链,将Rust代码编译为WebAssembly格局的二进制文件。这个生成的Wasm文件可以在阅读器中运转,或与其余支持WebAssembly的环境一同经常使用。
运转结果如下:
cargobuild--targetwasm32-unknown-unknown命令的「默逞强上天位」是在名目的target目录下,详细位置是:
target/wasm32-unknown-unknown/debug/
在这个目录下,咱们会找到生成的WebAssembly文件(理论是一个.wasm文件),以及其余与编译环节关系的文件。
图片
2.6构建Web主机
既然,咱们经过上述的魔法,将Rust程序编译为了可以在阅读器环境下援用口头的格局。「为了这口醋,咱们还专门包顿饺子」。
咱们须要一个Web主机来测试咱们的WebAssembly程序。咱们将经常使用Webpack,咱们须要创立三个文件:index.js、package.json和webpack.config.js。
上方的代码,咱们最相熟不过了,就不解释了。
//间接引入了,刚才编译后的文件construst=import('./pkg/hello_world.js');rust.then(m=>m.helloworld('World!')).catch(console.error);
package.json
{"scripts":{"build":"webpack","serve":"webpack-dev-server"},"devDependencies":{"@wasm-tool/wasm-pack-plugin":"0.4.2","text-encoding":"^0.7.0","-webpack-plugin":"^3.2.0","webpack":"^4.29.4","webpack-cli":"^3.1.1","webpack-dev-server":"^3.1.0"}}
webpack.config.js
constpath=require('path');constHtmlWebpackPlugin=require('html-webpack-plugin');constwebpack=require('webpack');constWasmPackPlugin=require("@wasm-tool/wasm-pack-plugin");module.exports={entry:'./index.js',output:{path:path.resolve(__dirname,'dist'),filename:'index.js',},plugins:[newHtmlWebpackPlugin(),newWasmPackPlugin({crateDirectory:path.resolve(__dirname,".")}),//让这个示例在不蕴含`TextEncoder`或`TextDecoder`的Edge阅读器中反常上班。newwebpack.ProvidePlugin({TextDecoder:['text-encoding','TextDecoder'],TextEncoder:['text-encoding','TextEncoder']})],mode:'development'};
装置指定的依赖。
npminstallwebpack--save-devnpminstallwebpack-cli--save-devnpminstallwebpack-dev-server--save-devnpminstallhtml-webpack-plugin--save-devnpminstall@wasm-tool/wasm-pack-plugin--save-devnpminstalltext-encoding--save-dev
2.7构建&运转程序
经常使用npmrunbuild构建程序。
经常使用npmrunserve运转HelloWorld程序
在阅读器中关上localhost:8080,咱们将看到一个显示HelloWorld!的弹窗。
图片
到目前为止,咱们曾经构建了一个wasm并且能够和js成功性能交互的名目。其实,到这里曾经成功了,咱们这篇文章的使命。但是,在这里戛但是止,觉得缺失点啥。所以,咱们继续深挖上方的名目的成功原理。
3.原理探析
在经常使用cargo和wasm_bindgen编译源代码时,会在pkg文件中「智能生成」以下文件:
这些文件也可以经过经常使用以下wasm-bindgen命令手动生成:
wasm-bindgentarget/wasm32-unknown-unknown/debug/hello_world.wasm--out-dir./pkg
阅读器调用顺序
以下显示了当咱们在阅读器中访问localhost:8080时出现的函数调用序列。
construst=import('./pkg/hello_world.js');rust.then(m=>m.helloworld('World!')).catch(console.error);
index.js导入了hello_world.js并调用其中的helloworld函数。
hello_world.js
上方是hello_world.js的内容,在其中它调用了helloworld_bg.wasm
import*aswasmfrom"./hello_world_bg.wasm";import{__wbg_set_wasm}from"./hello_world_bg.js";__wbg_set_wasm(wasm);export*from"./hello_world_bg.js";
hello_world_bg.js
//...省去了局部代码exportfunctionhelloworld(name){constptr0=passStringToWasm0(name,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);constlen0=WASM_VECTOR_LEN;wasm.helloworld(ptr0,len0);}
hello_world_bg.js文件是由wasm-bindgen智能生成的,它蕴含了用于将DOM和JavaScript函数导入到Rust中的JavaScript粘合代码。它还在生成的WebAssembly函数上向JavaScript地下了API。
RustWebAssembly专一于将WebAssembly与现有的JavaScript运行程序集成在一同。为了成功这一指标,咱们须要在JavaScript和WebAssembly函数之间「传递不同的值、对象或结构。这并不容易,由于须要协调两个不同系统的不同对象类型」。
更蹩脚的是,以后WebAssembly仅支持「整数」和「浮点数」,不支持字符串。这象征着咱们不能便捷地将字符串传递给WebAssembly函数。
要将字符串传递给WebAssembly,咱们须要「将字符串转换为数字」(请留意在webpack.config.js中指定的TextEncoderAPI),将这些数字放入WebAssembly的内存空间中,最后「前往一个指向字符串的指针」给WebAssembly函数,以便在JavaScript中经常使用它。在最后,咱们须要监禁WebAssembly经常使用的字符串内存空间。
假设咱们检查上方的JavaScript代码,这正是智能口头的操作。helloworld函数首先调用passStringToWasm。
图片
假设只是传递一个便捷的字符串,咱们或许可以自己解决,但思考到当触及到更复杂的对象和结构时,这个上班会很快变得十分复杂。这说明了wasm-bindgen在RustWebAssembly开发中的关键性。
反编译wasm到txt
在前面的步骤中,咱们留意到wasm-bindgen生成了一个hello_world.js文件,其中的函数调用到咱们生成的hello_world_bg.wasm中的WebAssembly代码。
基本上,hello_world.js充任其余JavaScript(如index.js)与生成的WebAssembly的helloworld_bg.wasm之间的桥梁。
咱们可以经过输入以下命令进一步探求helloworld_bg.wasm:
wasm2wathello_world_bg.wasm>hello_world.txt
这个命令经常使用wabt将WebAssembly转换为WebAssembly文本格局,并将其保留到一个hello_world.txt文件中。关上helloworld.txt文件,而后查找$helloworld函数。这是咱们在src/lib.rs中定义的helloworld函数的生成WebAssembly函数。
$helloworld函数
图片
在helloworld.txt中查找以下行:
(export"helloworld"(func$helloworld))
这一行导出了wasm.helloworld供宿主调用的WebAssembly函数。咱们经过hello_world_bg.js中的wasm.helloworld来调用这个WebAssembly函数。
图片
接上去,查找以下行:
(import"./hello_world_bg.js""__wbg_alert_9ea5a791b0d4c7a3"(func$hello_world::alert::__wbg_alert_9ea5a791b0d4c7a3::h93c656ecd0e94e40(type4)))
这对应于在hello_world_bg.js中生成的以下JavaScript函数:
exportfunction__wbg_alert_9ea5a791b0d4c7a3(){returnlogError(function(arg0,arg1){alert(getStringFromWasm0(arg0,arg1));},arguments)};
这是wasm-bindgen提供的「粘合局部」,协助咱们在WebAssembly中经常使用JavaScript函数或DOM。
最后,让咱们看看wasm-bindgen生成的其余文件。
hello_world.d.ts
这个.d.ts文件蕴含JavaScript粘合的TypeScript类型申明,假设咱们的现有JavaScript运行程序正在经常使用TypeScript,它会很有用。咱们可以对调用WebAssembly函数启动「类型审核」,或许让咱们的IDE提供智能成功。假设咱们不经常使用TypeScript,可以安保地疏忽这个文件。
package.json
package.json文件蕴含无关生成的JavaScript和WebAssembly包的元数据。它会智能从咱们的Rust代码中填充一切npm依赖项,并使咱们能够颁布到npm。
4.内容拓展
再次看一下以下代码:
hello_world_bg.js
functionhelloworld(name){constptr0=passStringToWasm0(name,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);constlen0=WASM_VECTOR_LEN;wasm.helloworld(ptr0,len0);}
该代码用于调配和监禁内存,这一切都是「由程序智能解决」的。不须要渣滓回收器或完整的框架引擎,使得经常使用Rust编写的WebAssembly运行程序或模块变得小巧且提升。其余须要渣滓回收器的言语将须要蕴含用于其底层框架引擎的wasm代码。因此,无论它们有如许提升,其大小都不会小于Rust提供的大小。这使得RustWebAssembly成为一个不错的选用,假设咱们须要将小型WebAssembly模块集成或注入到JavaScriptWeb运行程序中。
除了HelloWorld之外,还有一些其余须要留意的事项:
经常使用wasm-bindgen,咱们可以经过经常使用extern在RustWebAssembly中调用JavaScript函数。请记住src/lib.rs中的以下代码:
#[wasm_bindgen]extern"C"{fnalert(s:&str);}
Web具备少量API,从DOM操作到WebGL再到WebAudio等等。因此,假设咱们的RustWebAssembly程序增长,并且咱们须要对WebAPI启动屡次不同的调用,咱们将须要花期间编写少量的extern代码。
这象征着假设咱们经常使用web-sys,可以节俭期间,而不用编写extern代码。
图片
引入web-sys
将web-sys减少为Cargo.toml的依赖项:
[dependencies]wasm-bindgen="0.2"[dependencies.web-sys]version="0.3"features=[]
为了坚持构建速度十分快,web-sys将每个Web接口都封装在一个Cargo个性前面。在API文档中找到咱们要经常使用的类型或方法;它将列出必定启用的个性能力访问该API。
例如,假设咱们要查找window.resizeTo函数,咱们会在API文档中搜查resizeTo。咱们将找到web_sys::Window::resize_to函数,它须要启用Window个性。要访问该函数,咱们在Cargo.toml中启用Window个性:
[dependencies.web-sys]version="0.3"features=["Window"]
调用这个方法:
usewasm_bindgen::prelude::*;useweb_sys::Window;#[wasm_bindgen]pubfnmake_the_window_small(){//调整窗口大小为500pxx500px。letwindow=web_sys::window().unwrap();window.resize_to(500,500).expect("无法调整窗口大小");}
这段代码的目的是调整阅读器窗口的大小为500x500像素,并展示了如何经常使用web-sys和启用的Cargo个性来调用WebAPI。
rust语言能干什么
使用Rust语言能干什么?1. 编写系统级代码Rust是一种系统级编程语言,最早是由Mozilla设计和开发的。 Rust提供了高效、安全和并发的编程体验,可用于开发操作系统、编写网络协议和构建嵌入式系统。 作为一种系统级编程语言,Rust拥有高效的内存管理和优秀的性能表现。 使用Rust编写的程序可以比其他语言的程序更加安全和稳定。 此外,Rust还有一个独特的特性:防止空指针异常,从而提高代码的可靠性和安全性。 2. 开发游戏Rust的高效性能、并发性以及安全性,使其成为游戏编程的理想选择。 Rust的环境支持开发底层图形API,只需要少量代码就可以实现高质量的游戏引擎。 Rust还可以编译为WebAssembly,在Web游戏开发上可以更好的进行宝贵的代码再利用,更加节省开发时间和精力。 3. 编写安全的Web应用程序Rust支持编写高性能,线程安全和内存安全的Web应用程序。 Rust拥有更好的内存控制和类型系统,可以避免大部分常见的安全漏洞,如Buffer Overflow和Null Pointer Derefence。 Rust的强大的错误机制,允许开发者在编译时检测错误并及时处理,从而减少程序崩溃的可能性。 4. 编写网络服务Rust提供高效的I/O处理,使其成为编写网络服务的良好选择。 在Rust中,开发者可以快速地编写高的 Web服务器,DNS服务器,代理服务器等,完全不必担心性能问题。 事实上,许多项目已经证明了Rust比其他Web开发语言,如Ruby,Python和Go等,在性能和可靠性方面提供了更好的表现。 而且,使用Rust编写的Web服务更容易部署和维护,使其成为企业应用的首选。 5. 实现并发编程Rust拥有卓越的并发编程特性,可以轻松地编写并发程序。 Rust的所有权和借用机制可以保证在编写并发程序时,不存在竞争概率,避免了常见的程序错误和死锁现象。 并且,Rust的并发编程库提供充分的支持,开发者可以专注于并发逻辑编程,而无需花费大量时间在语言层面的细节上。 6. 编写嵌入式系统Rust作为一种系统级编程语言,也可以用于编写嵌入式系统。 与其他编程语言相比,Rust提供了更好的类型安全性和内存管理。 Rust的高效性能和并发性,使其能够处理高复杂性的嵌入式系统。 最重要的是,Rust的所有权和借用机制能够避免缓冲区溢出等常见问题,如此高度的可靠性对于嵌入式应用程序来说是至关重要的。 7. 编写机器学习程序Rust的高性能,安全和并发性,使其成为新一代机器学习程序的领导者。 Rust可以轻松处理大数据集,Rust的并发性可以大大提高机器学习的性能,同时提供更安全和更可靠的代码。 Rust社区中也有一些机器学习的成熟开源库,如rustlearn,提供了完整的机器学习功能,包括深度学习,神经网络等。 值得注意的是,Rust将成为未来机器学习发展的必要工具之一。 8. 编写物联网应用程序在物联网时代,硬件设备数量急剧增长。 Rust作为一种高安全性和高性能性的语言,将成为物联网应用程序的首选语言之一。 相比其他编程语言,Rust能够更好地保证代码的安全性和可靠性,同时能够轻松地实现网络通信和数据存储。 此外,Rust的性能也非常适合物联网应用程序,能够处理大量的数据和复杂的计算。 结论通过本文的介绍,我们可以看出Rust的应用领域是非常广泛的。 Rust作为一种安全、高效、并发的系统级编程语言,已经被广泛地应用于各种领域,如游戏开发、Web开发、嵌入式系统开发、机器学习等。 在未来,Rust的应用前景将会更加广阔。 因此,学习Rust并掌握其编程特性将具有重要的实际意义,并为您事业发展带来更广阔的前景。
编程时选用的程序设计语言,对软件的开发与维护的影响?
【CSDN 编者按】“如果我们把人类文明想象成汽车的话,那么软件开发行业就相当于汽车的引擎,编程语言就像引擎的燃料。”作为一名开发者,需跟随技术潮流的发展来学习新技术。2020年,你有计划新学一门编程语言吗?
本文作者从一名架构师的角度,详细分析了7种现代编程语言的优点与功能,你对哪门语言最感兴趣呢?
作者 | Md Kamaruzzaman,软件架构师
译者 | 弯月,责编 | 伍杏玲
封图| CSDN 下载于视觉中国
出品 | CSDN(ID:CSDNnews)
以下为译文:
如果我们把人类文明想象成汽车的话,那么软件开发行业就相当于汽车的引擎,而编程语言就像引擎的燃料。作为一名开发者,今年你应该学习哪种编程语言呢?
学习一种新的编程语言无疑是时间、精力和智力上的巨大投资, 但是学习一种新的编程语言可以提升你的软件开发技术力,促进你的职业发展。
在这里,我将献上一份现代编程语言的列表,这些语言不仅有助于提高你的生产力,而且还可以促进你的职业发展,并让你成长为更优秀的开发人员。这份列表还涵盖了非常广泛的领域:系统编程、应用程序开发、Web开发、科学计算等。
什么是现代编程语言?
“现代编程语言”这个说法本身就很含糊。许多人认为Python和JavaScript等语言是现代编程语言,还认为Java是一种古老的编程语言。实际上,这几种语言大约在同一时间出现:1995年。
大多数主流编程语言是上个世纪开发的:七十年代(如C)、八十年代(如C ++)、九十年代(如Java、Python、JavaScript)。这些语言在设计上并没有考虑现代软件开发生态系统:多核CPU、GPU、快速的互联网、移动设备、容器和云等。尽管许多语言中的许多功能都已进行一些改进,如并发等,而且在不断调整自己以适应时代,但它们依然保留了向后兼容性,无法抛弃那些过时的旧功能。
在这方面,Python就做得很好(某种意义上也未必是好事),Python 2和Python 3两者之间有明确的分界线。很多语言常常会为解决同一个问题提供十余种的方法,同时又没有顾及到开发人员的感受。根据StackOverflow的开发人员调查,大多数旧时的主流编程语言在“最可怕的语言”排名都名列前茅:
如果非要在新旧编程语言之间划个界限的话,那么应该是2007年6月29日,也就是第一台iPhone发行的时候。在这之后,编程语言界发生了很大变化。因此,在本文的列表中,我只考虑2007年以后的编程语言。
为什么要学习新语言?
首先,现代编程语言充分利用现代计算机硬件(多核CPU、GPU、TPU)、移动设备、大量数据、高速互联网、容器和云的优势。大多数现代编程语言会关注开发人员的体验,比如:
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。