百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

Golang和Rust语言常见功能/库

bigegpt 2024-09-17 12:40 97 浏览

时下最流行、最具发展前途的的两门语言是Golang和Rust。Golang语言简洁、高效、并发、并且有个强大的囊括了常见功能标准库。与之相对比,Rust语言则主要是安全、高性能。虽然Rust没有golang那种"内置电池(Batteries included)"的标准库,但是Rust的第三方库(crate,板条箱)极大补充了Rust精炼基本库的功能。本文我们就介绍一下Golang和Rust常用的库功能。

参数处理

Golang标准库中提供了功能。flag库是非常基础的功能,在实践上也非常有用,在做命令行交互程序时候必不可少。

package main
import "flag"
var (
program = flag.String("p", "", "h program to compile/run")
outFname = flag.String("o", "", "if specified, write the webassembly binary created by -p here")
watFname = flag.String("o-wat", "", "if specified, write the uncompiled webassembly created by -p here")
port = flag.String("port", "", "HTTP port to listen on")
writeTao = flag.Bool("koan", false, "if true, print the h koan and then exit")
writeVersion = flag.Bool("v", false, "if true, print the version of h and then exit")
)

上述代码会生成一些程序包全局变量,其中将包含命令行参数的值。

在Rust中,常用的命令行解析包是structopt。但是,其工作方式与Golang flag程序包有所不同。structopt会选项加载到结构中,而非全局可变变量。主要因为Rust语言编程实践中,基本上都会避免全局可变的变量。在大多数情况下,带有包的全局变量flag是可以的,但前提是必须在程序真正开始执行其需要做的工作之前将它们写入到程序中。

一个简单示例源自于pahi库源码:

#[derive(Debug, StructOpt)]
#[structopt(
name = "pa'i",
about = "A WebAssembly runtime in Rust meeting the Olin ABI."
)]
struct Opt {
#[structopt(short, long, default_value = "cranelift")]
backend: String,
#[structopt(short, long)]
function_log: bool,
#[structopt(short, long)]
no_cache: bool,
#[structopt()]
fname: String,
#[structopt(short, long, default_value = "_start")]
entrypoint: String,
#[structopt()]
args: Vec<String>,
}

Rust编译器会生成所需的参数解析代码,然后可以使用:

fn main() {
let opt = Opt::from_args();
debug!("args: {:?}", opt.args);
if opt.backend != "cranelift" {
        return Err(format!(
            "wanted backend to be cranelift, got: {}",
            opt.backend
        ));
}

错误处理

Golang的标准库具有error接口,可以创建一个描述类型的函数,函数描述为什么功能无法按预期执行,Golang程序必须先做好错误处理。比如:

func Write(w io.Writer, buf []byte) error {
_, err := w.Write(buf)
if err != nil {
log.Println("unable to write:", err)
return err
}
return nil

Rust也具有Error 特性,它使还可以创建一个描述函数为何无法实现其预期功能的类型。这儿我们介绍更加易用的thiserror板条箱构建自定义错误类型:

[dependencies]
thiserror = "1"

然后,在程序中使用:

use std::fmt;
use thiserror::Error;
#[derive(Debug, Error)]
struct Divide0?;
impl fmt::Display for Divide0? {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "不能被零整除!")
}
}

日志记录

Go标准库中也自带了log库。该库是一个非常有争议的记录器,它的日志记录缺乏日志记录级别和上下文感知值之类的功能。

package main
import (
"log"
)
func init() {
log.SetPrefix("TRACE: ")
log.SetFlags(log.Ldate | log.Lmicroseconds | log.Llongfile)
}
func main() {
log.Println("message")
log.Fatalln("fatal message")
log.Panicln("panic message")
}
-------------------------------
TRACE: 2020/09/09 14:24:32.868375 TestLog.go:15: message
TRACE: 2020/09/09 14:24:32.962329 TestLog.go:18: fatal message
Process finished with exit code 1

在Rust中,有一个板条箱,这是一个非常简单的包,它使用error!,warn!,info!,debug!和trace!宏分别关联到最高和最低日志打印水平。同样要使用log板条箱,先要增加的项目中,即添加到Cargo.toml的依赖部分。

[dependencies]

log = "0.4"

然后,就可以使用了:

use log::{error, warn, info, debug, trace};
fn main() {
trace!("starting main");
debug!("debug message");
info!("this is some information");
warn!("oh no something bad is about to happen");
error!("oh no it's an error");
}

注意,默认该库日志记录是不会记录到本地文件中的。要记录日志还需要其他库。

pretty_env_logger是和log买一送一,最常搭配使用的板条箱。同样,先添加项目依赖:

[dependencies]
log = "0.4"
pretty_env_logger = "0.4"

然后,在代码中使用:

use log::{error, warn, info, debug, trace};
fn main() {
pretty_env_logger::init();
trace!("这是一个示例程序。");
debug!("调试信息xxx。");
info!("程序正在运行中。");
warn!("[WARN]程序有些参数配置有问题。");
error!("[ERROR]程序发生严重错误!");


然后在启动时候增加,日志级别参数RUST_LOG=trace 运行:

env RUST_LOG=trace cargo run
 
Compiling errex v0.1.0 (/home/lz/test/rust/commoncrate/errex)
    Finished dev [unoptimized + debuginfo] target(s) in 1.32s
     Running `target/debug/errex`
 TRACE errex > 这是一个示例程序。
 DEBUG errex > 调试信息xxx。
 INFO  errex > 程序正在运行中。
 WARN  errex > [WARN]程序有些参数配置有问题。
 ERROR errex > [ERROR]程序发生严重错误!



序列化/反序列化

Golang在标准库内置了 包用来实现JSON编码/解码功能。我们可以定义可以轻松读取和写入JSON的类型。下面一个例子:

{
"id": 3137,
"author": {
"id": 420,
"name": "Chongchong"
},
"body": "Hello,This is Chongchong web!",
"in_reply_to": 3135
}

在Golang中,可以生成如下的结构体:

type Author struct {
ID int `json:"id"`
Name string `json:"name"`
}


type Comment struct {
ID int `json:"id"`
Author Author `json:"author"`
Body string `json:"body"`
InReplyTo int `json:"in_reply_to"`
}

Rust没有开箱即用的功能,需要使用第三方板条箱,最常用的一个库是serde,可以跨JSON和能想到的所有其他序列化方法使用。

[dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"

注意,上面serde的依赖配置,和其他包有差异。

Golang的JSON包通过使用struct标签作为元数据来工作,但是Rust没有,需要改用Rust的衍生功能。

因此,要将serde用于的注释类型:

use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Author {
pub id: i32,
pub name: String,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Comment {
pub id: i32,
pub author: Author,
pub body: String,
pub in_reply_to: i32,
}

然后,使用以下代码解析Json:

fn main() {
let data = r#"
{
"id": 3137,
"author": {
"id": 420,
"name": "Chongchong"
},
"body": "Hello,This is Chongchong web!",
"in_reply_to": 3135
}
"#;
let c: Comment = serde_json::from_str(data).expect("json to parse");
println!("comment: {:#?}", c);
}

cargo run

...
Finished dev [unoptimized + debuginfo] target(s) in 0.04s
     Running `target/debug/serdeex`
comment: Comment {
    id: 3137,
    author: Author {
        id: 420,
        name: "Chongchong",
    },
    body: "Hello,This is Chongchong web!",
    in_reply_to: 3135,
}


Web开发

在Web开发中HTTP包必不可少的。Golang中可使用net/http充当生产级HTTP客户端和服务器。

import (
"net/http"
"fmt"
"log"
)

func sayhelloGolang(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
fmt.Println("path", r.URL.Path)
w.Write([]byte("Hello Chongchong!"))
}

func main() {
http.HandleFunc("/",hello)
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}

它可以让我们非常轻松地进行Web开发。Rust标准库没有开箱即用的HTTP功能,但是Web的框架也非常丰富。

客户端

对于HTTP客户端,可以使用。它还可以与serde无缝集成,以允许从HTTP解析JSON:

[dependencies]
reqwest = { version = "0.10", features = ["json"] }
tokio = { version = "0.2", features = ["full"] }

tokio默认情况下Rust不附带异步运行时,tokio大约等同于Golang运行时帮助处理的大多数重要事项。简单实例如下:



运行此命令:

cargo run 
...
Finished dev [unoptimized + debuginfo] target(s) in 3.31s
     Running `target/debug/webcer`
Status: 200 OK
Body:
<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<title>hyper.rs | hyper</title>
<meta name="description" content="">



结合其他功能,reqwest可以做作为一个功能强大的HTTP客户端。

服务器端

至于HTTP服务器,可以使用warp板条箱。warp是一个建立在Rust的类型系统之上的HTTP服务器框架。

[dependencies]
tokio = { version = "0.2", features = ["macros"] }
warp = "0.2"

让我们写个简单的"Hello,Chongchong"示例:

use warp::Filter;
#[tokio::main]
async fn main() {
// GET /hello/Chongchong=> 200 OK with body "Hello, Chongchong!"
let hello = warp::path!("hello" / String)
.map(|name| format!("Hello, {}!", name));
warp::serve(hello)
.run(([127, 0, 0, 1], 3030))
.await;
}

然后通过127.0.0.1:3030/hello/Chongchong,就可以提示Hello, Chongchong!。

对 warp应用可以使用其or模式构建多条Web路由:

let hello = warp::path!("hello" / String)
.map(|name| format!("Hello, {}!", name));
let health = warp::path!(".within" / "health")
.map(|| "OK");
let routes = hello.or(health);

还可通过过滤器将其他数据类型注入到处理程序中:

let fact = {
let facts = pfacts::make();
warp::any().map(move || facts.clone())
};
let fact_handler = warp::get()
.and(warp::path("fact"))
.and(fact.clone())
.and_then(give_fact);

warp是功能强大的HTTP服务器,可以跨生产级Web应用程序所需的所有内容工作。

模版

Web开发中要常用模版来特定化页面的输出。Golang的标准库还包括HTML和纯文本模板包html/templatetext/template。在Rust中有很多用于HTML模板化的解决方案,比如ructe板条箱。ructe使用Cargo的build.rs功能在编译时为其模板生成Rust代码。这样就可以将HTML模板编译成结果应用程序二进制文件,从而以惊人的速度呈现它们。

添加Cargo.toml:

[build-dependencies]
ructe = { version = "0.12", features = ["warp02"] }
还依赖mime板条箱:
[dependencies]
mime = "0.3.0"

完成此操作后,templates在当前工作目录中创建一个新文件夹。创建一个名为的文件hello.rs.html,并将以下内容放入其中:

@(title: String, message: String)
<html>
<head>
<title>@title</title>
</head>
<body>
<h1>@title</h1>
<p>@message</p>
</body>
</html>

然后使用模板templates.rs:

use warp::{http::Response, Filter, Rejection, Reply};
async fn hello_html(message: String) -> Result<impl Reply, Rejection> {
Response::builder()
.html(|o| templates::index_html(o, "Hello".to_string(), message).unwrap().clone()))
}

在src/main.rs底部,通过以下语句引入模版定义:

include!(concat!(env!("OUT_DIR"), "/templates.rs"));

在main()函数中调用:

let hello_html_rt = warp::path!("hello" / "html" / String)
.and_then(hello_html);
let routes = hello_html_rt.or(health).or(hello);

总结

本文我们介绍了Golang和Rust中常用的功能包括命令行参数解析、错误处理、日志、Json处理和Web库,我们可以发现基本上这些功能都在Golang标准库中都提供了,而Rust则要引入额外的板条箱,但是借助强大的Cargo包管理工具,其使用也非常便捷。

相关推荐

方差分析简介(方差分析通俗理解)

介绍方差分析(ANOVA,AnalysisofVariance)是一种广泛使用的统计方法,用于比较两个或多个组之间的均值。单因素方差分析是方差分析的一种变体,旨在检测三个或更多分类组的均值是否存在...

正如404页面所预示,猴子正成为断网元凶--吧嗒吧嗒真好吃

吧嗒吧嗒,绘图:MakiNaro你可以通过加热、冰冻、水淹、模塑、甚至压溃压力来使网络光缆硬化。但用猴子显然是不行的。光缆那新挤压成型的塑料外皮太尼玛诱人了,无法阻挡一场试吃盛宴的举行。印度政府正...

Python数据可视化:箱线图多种库画法

概念箱线图通过数据的四分位数来展示数据的分布情况。例如:数据的中心位置,数据间的离散程度,是否有异常值等。把数据从小到大进行排列并等分成四份,第一分位数(Q1),第二分位数(Q2)和第三分位数(Q3)...

多组独立(完全随机设计)样本秩和检验的SPSS操作教程及结果解读

作者/风仕在上一期,我们已经讲完了两组独立样本秩和检验的SPSS操作教程及结果解读,这期开始讲多组独立样本秩和检验,我们主要从多组独立样本秩和检验介绍、两组独立样本秩和检验使用条件及案例的SPSS操作...

方差分析 in R语言 and Excel(方差分析r语言例题)

今天来写一篇实际中比较实用的分析方法,方差分析。通过方差分析,我们可以确定组别之间的差异是否超出了由于随机因素引起的差异范围。方差分析分为单因素方差分析和多因素方差分析,这一篇先介绍一下单因素方差分析...

可视化:前端数据可视化插件大盘点 图表/图谱/地图/关系图

前端数据可视化插件大盘点图表/图谱/地图/关系图全有在大数据时代,很多时候我们需要在网页中显示数据统计报表,从而能很直观地了解数据的走向,开发人员很多时候需要使用图表来表现一些数据。随着Web技术的...

matplotlib 必知的 15 个图(matplotlib各种图)

施工专题,我已完成20篇,施工系列几乎覆盖Python完整技术栈,目标只总结实践中最实用的东西,直击问题本质,快速帮助读者们入门和进阶:1我的施工计划2数字专题3字符串专题4列表专题5流程控制专题6编...

R ggplot2常用图表绘制指南(ggplot2绘制折线图)

ggplot2是R语言中强大的数据可视化包,基于“图形语法”(GrammarofGraphics),通过分层方式构建图表。以下是常用图表命令的详细指南,涵盖基本语法、常见图表类型及示例,适合...

Python数据可视化:从Pandas基础到Seaborn高级应用

数据可视化是数据分析中不可或缺的一环,它能帮助我们直观理解数据模式和趋势。本文将全面介绍Python中最常用的三种可视化方法。Pandas内置绘图功能Pandas基于Matplotlib提供了简洁的绘...

Python 数据可视化常用命令备忘录

本文提供了一个全面的Python数据可视化备忘单,适用于探索性数据分析(EDA)。该备忘单涵盖了单变量分析、双变量分析、多变量分析、时间序列分析、文本数据分析、可视化定制以及保存与显示等内容。所...

统计图的种类(统计图的种类及特点图片)

统计图是利用几何图形或具体事物的形象和地图等形式来表现社会经济现象数量特征和数量关系的图形。以下是几种常见的统计图类型及其适用场景:1.条形图(BarChart)条形图是用矩形条的高度或长度来表示...

实测,大模型谁更懂数据可视化?(数据可视化和可视化分析的主要模型)

大家好,我是Ai学习的老章看论文时,经常看到漂亮的图表,很多不知道是用什么工具绘制的,或者很想复刻类似图表。实测,大模型LaTeX公式识别,出乎预料前文,我用Kimi、Qwen-3-235B...

通过AI提示词让Deepseek快速生成各种类型的图表制作

在数据分析和可视化领域,图表是传达信息的重要工具。然而,传统图表制作往往需要专业的软件和一定的技术知识。本文将介绍如何通过AI提示词,利用Deepseek快速生成各种类型的图表,包括柱状图、折线图、饼...

数据可视化:解析箱线图(box plot)

箱线图/盒须图(boxplot)是数据分布的图形表示,由五个摘要组成:最小值、第一四分位数(25th百分位数)、中位数、第三四分位数(75th百分位数)和最大值。箱子代表四分位距(IQR)。IQR是...

[seaborn] seaborn学习笔记1-箱形图Boxplot

1箱形图Boxplot(代码下载)Boxplot可能是最常见的图形类型之一。它能够很好表示数据中的分布规律。箱型图方框的末尾显示了上下四分位数。极线显示最高和最低值,不包括异常值。seaborn中...