go switch的6种用法【译】

文章原文链接为 https://blog.devtrovert.com/p/switch-in-go-6-ways-to-use-it 照片由 Zbyněk Skrčený 在 Unsplash 上拍摄 Go 以其简单而闻名,但我注意到并不是每个人都熟悉 switch 语句在这种语言中的多功能性。 首先,如果您不熟悉 Go 的 switch 语句,与其他语言相比,它可能看起来有点不同。这是一个简单的例子来展示它的样子: func main() { var i int = 1 switch i { case 1: fmt.Println("i is 1") case 2: fmt.Println("i is 2") default: fmt.Println("i is not 1 or 2") } } Go 的 switch 的一个很酷的事情是,一旦找到匹配项,它就会停止,你不需要在每个 case 的末尾添加一个 break 语句。 但不仅仅如此。 Go 中的 switch 语句有两部分:分号之前的部分是初始化器,分号之后的部分是我们要检查的值。 我们可以选择同时使用、使用其中之一或都不使用: switch initializer; value {} switch initializer {} switch value {} switch {} 有趣,对吧?...

February 17, 2024 · 3 min · czyt

跟AI学习Rust

本文为学习rust过程中,向ai提问的内容汇总。配套图书为《Rust程序设计 第2版》 基础 迭代器 fuse Cow 在 Rust 中,Cow 是 “Clone on Write” 的缩写,它是一个智能指针类型,属于标准库的 std::borrow 模块。Cow 可以用来封装一个可能是借用(borrowed)也可能是拥有(owned)的值。Cow类型实际上是一个枚举类型,定义如下: enum Cow<'a, B> where B: 'a + ToOwned + ?Sized, { Borrowed(&'a B), Owned(<B as ToOwned>::Owned), } 其中 B 是被借用的类型,而 <B as ToOwned>::Owned 是该类型的拥有版本。一个具体类型必须实现 ToOwned trait,这样 Cow 才能根据需要clone被借用的数据产生一个拥有的副本。 实际用途: Cow 最大的优势在于它提供了一种方法来延迟昂贵的克隆操作,直到真正需要修改数据时才进行,这样可以提高性能。它经常被用于以下场景: 优化读多写少的情况:当数据通常只是被读取,但偶尔需要被修改时,Cow 可以避免不必要的克隆操作。 提供 API 的灵活性:某些函数可能需要对输入数据做出修改,但并不总是需要。这时,使用 Cow 作为参数类型允许调用者传递拥有的也可以是借用的值,增加了 API 的使用灵活性。 处理字符串数据:当处理字符串切片(&str)和字符串(String)时,Cow<str> 可以根据实际情况借用静态字符串或者拥有一个可变的字符串副本。 避免生命周期问题:当要返回一个引用但函数的实际行为可能需要返回一个拥有的值时,使用 Cow 可以更好地管理生命周期问题。 示例: 你可以在下面的示例中看到 Cow 的用法: use std::borrow::Cow; fn greeting(name: &str) -> Cow<str> { if name....

February 16, 2024 · 11 min · czyt

使用结构或可变参数选项简化go函数签名【译】

文章内容来自func25的 twitter 在Go中设计函数时,我们可能会遇到需要传递大量参数的情况。 这可能会影响函数的目的,并使维护代码成为一件苦差事,特别是当涉及相同类型的参数时。 为了保持整洁,请考虑两种策略: 选项结构。 可变选项。 选项结构体 将参数捆绑到一个结构中,这不仅增强了可读性,还简化了参数传递。 什么时候使用它? 你的函数有一个很长的参数列表。 您的目标是自记录代码,因为结构字段本质上描述了它们的用途(通过名称)。 您希望轻松设置默认值或灵活修改选项。 使用此模式时, context.Context 应保留为单独的参数,而不应包含在选项结构中。 这是由于上下文在控制请求范围值、截止日期和取消信号方面的独特作用。 但在使用时有一些小技巧: 该结构应该向后兼容,以便在添加新字段时,我们不会破坏之前的任何内容。 我们始终可以在处理结构之前对其进行验证。 考虑隐藏您的选项结构(使其不导出),然后公开 NewXXX() 函数并在那里设置默认值。 可变参数选项 此方法利用 Go 的函数功能,允许您以更简洁的方式传递灵活数量的选项。 它在以下情况下是理想的: 该功能需要高度可配置。 大多数选项是可选的或很少使用。 您更喜欢简洁的调用站点。 设置默认值比使用可选结构更容易,您不需要隐藏它,只需将默认值直接放在 ConnectToDatabase 中即可。

February 14, 2024 · 1 min · czyt

在 Rust 中使用 Axum【译】

本文原文地址为 https://www.shuttle.rs/blog/2023/12/06/using-axum-rust Rust Web 生态系统中有如此多的后端 Web 框架,很难知道该选择什么。尽管在更早的过去,您可能会看到 Rocket 在受欢迎程度方面跃居排行榜首位,但现在通常是 Axum 和 actix-web 展开激烈的竞争,Axum 慢慢地登上了榜首。在本文中,我们将深入研究 Axum,这是一个由 Tokio 团队支持的用于制作 Rust REST API 的 Web 框架,它易于使用,并且与 Tower 具有超兼容性,Tower 是一个强大的可重用、模块化组件库,用于构建网络应用程序。 在本文中,我们将全面了解如何使用 Axum 编写 Web 服务。这也将包括 0.7 的更改。 Axum的路由 Axum 遵循 REST 风格的 API(例如 Express)的风格,您可以在其中创建处理函数并将它们附加到 axum 的 axum::Router 类型。路线的示例可能如下所示: async fn hello_world() -> &'static str { "Hello world!" } 然后我们可以将它添加到我们的路由器中,如下所示: use axum::{Router, routing::get}; fn init_router() -> Router { Router::new() .route("/", get(hello_world)) } 为了使处理函数有效,它需要是 axum::response::Response 类型或实现 axum::response::IntoResponse 。这已经针对大多数原始类型和 Axum 自己的所有类型实现了 - 例如,如果我们想要将一些 JSON 数据发送回用户,我们可以使用 Axum 的 JSON 类型作为返回类型来轻松实现这一点, axum::Json 类型包装了我们想要发回的任何内容。正如您在上面看到的,我们还可以单独返回一个字符串(切片)。...

January 30, 2024 · 6 min · czyt

Rust宏示例和实践【译】

原文链接为 https://earthly.dev/blog/rust-macros/ ,文章大部分使用机器翻译,小部分进行了文字调整。 本文深入探讨 Rust 宏的强大功能和多功能性。 Earthly 保证构建过程与您创建的宏一样强大。了解更多关于地球的信息。 在 Rust 中,宏是使用通常称为元编程的技术生成其他 Rust 代码的代码片段。宏在编译期间被扩展,并且宏的输出被插入到程序的源代码中。 最著名的宏示例是 println! 。尽管它看起来像函数并且使用起来也像函数,但它实际上在编译过程中进行了扩展,并且 println! 调用被替换为更复杂的实现代码。 在本文中,您将看到一些宏的实际示例,并了解一些有关如何最好地使用它们的提示和技巧。 Rust 宏基础知识 本教程假设您熟悉 Rust 编程的基础知识。 在 Rust 中,有两种类型的宏:声明性宏和过程性宏。逐一查看: 声明性宏 声明性宏是最简单的宏类型,由 macro-rules! 宏定义。它们的外观和行为与 match 表达式类似。 match 表达式将表达式作为输入,并将其与一组预定义模式进行匹配并运行相应的代码。类似地,声明性宏将一段 Rust 源代码作为输入,将源代码与一组预定义的结构进行匹配,并且在成功匹配时,将代码替换为与匹配模式关联的代码。 以下示例显示了正在运行的声明性宏: declarative_macro.rs//declarative_macro.rs macro_rules! greetings { ($x: expr) => { println!("Hello, {}", $x); }; } fn main() { greetings!("Earthly"); // Prints "Hello, Earthly" } 这里,宏被命名为 greetings 并用 macro_rules! 定义。在宏主体中,只有一种模式: ($x: expr) => { ....

January 28, 2024 · 7 min · czyt

在 Rust 中使用 Serde【译】

本文原文链接为 https://www.shuttle.rs/blog/2024/01/23/using-serde-rust 。大部分使用机器翻译,个人对机器翻译内容进行了部分润色,对于部分内容进行了增补。 在本文中,我们将讨论 Serde、如何在 Rust 应用程序中使用它以及一些更高级的提示和技巧。 什么是serde? serde Rust create用于高效地序列化和反序列化多种格式的数据。它通过提供两个可以使用的trait来实现这一点,恰当地命名为 Deserialize 和 Serialize 。作为生态系统中最著名的 crate 之一,它目前支持 20 多种类型的序列化(反序列化)。 首先,您需要将 crate 安装到您的 Rust 应用程序中: cargo add serde 使用serde 反序列化和序列化数据 序列化和反序列化数据的简单方法是添加 serde derive 功能。这会添加一个宏,您可以使用它来自动实现 Deserialize 和 Serialize - 您可以使用 --features 标志( -F 来实现)短的): cargo add serde -F derive 然后我们可以将宏添加到我们想要实现 Deserialize 或 Serialize 的任何struct体或enum(枚举)中: use serde::{Deserialize, Serialize}; #[derive(Deserialize, Serialize)] struct MyStruct { message: String, // ... the rest of your fields } 这允许我们使用任何支持 serde 的包在所述格式之间进行转换。作为示例,让我们使用 serde-json 与 JSON 格式相互转换:...

January 25, 2024 · 6 min · czyt

转换数字到Excel列字母实现

根据微软官方文档,excel最大支持1,048,576 行, 16,384 列。下面的代码并未处理这一限制。 Rust 实现代码: fn convert_to_title(mut n: i32) -> String { let mut result = String::new(); while n != 0 { n -= 1; let letter = (n % 26) as u8 + b'A'; result.insert(0, letter as char); n /= 26; } result } #[test] fn test_convert_to_title() { let aa = convert_to_title(27); assert_eq!(aa, "AC"); } Go 实现代码: func convertToTitle(n int) string { result := "" for n > 0 { n-- letter := n%26 result = string('A'+letter) + result n /= 26 } return result } C# 实现代码:...

January 25, 2024 · 1 min · czyt

关于七牛qetag算法的一些记录

背景 今天做七牛相关接口开发的时候发现七牛的文件查询列表返回,有个hash字段,但是不知道是怎么进行计算的。后来查询到七牛的官方仓库 qetag.官方对这个算法的描述是这样的: qetag 是一个计算文件在七牛云存储上的 hash 值(也是文件下载时的 etag 值)的实用程序。 七牛的 hash/etag 算法是公开的。算法大体如下: 如果你能够确认文件 <= 4M,那么 hash = UrlsafeBase64([0x16, sha1(FileContent)])。也就是,文件的内容的sha1值(20个字节),前面加一个byte(值为0x16),构成 21 字节的二进制数据,然后对这 21 字节的数据做 urlsafe 的 base64 编码。 如果文件 > 4M,则 hash = UrlsafeBase64([0x96, sha1([sha1(Block1), sha1(Block2), …])]),其中 Block 是把文件内容切分为 4M 为单位的一个个块,也就是 BlockI = FileContent[I*4M:(I+1)*4M]。 为何需要公开 hash/etag 算法?这个和 “消重” 问题有关,详细见: https://developer.qiniu.com/kodo/kb/1365/how-to-avoid-the-users-to-upload-files-with-the-same-key http://segmentfault.com/q/1010000000315810 为何在 sha1 值前面加一个byte的标记位(0x16或0x96)? 0x16 = 22,而 2^22 = 4M。所以前面的 0x16 其实是文件按 4M 分块的意思。 0x96 = 0x80 | 0x16。其中的 0x80 表示这个文件是大文件(有多个分块),hash 值也经过了2重的 sha1 计算。 语言封装 C# 实现 基于官方仓库的csharp代码做了部分修改...

January 22, 2024 · 3 min · czyt

Golang 高级时间工具函数

本文为 https://medium.com/canopas/golang-date-time-utilities-part-2-b1192eb04842 文章的翻译。正文部分进行了部分调整。 背景介绍 在编程世界中,处理日期和时间是一项常见的任务,通常需要精确性和灵活性。 虽然 Go 编程语言的标准库提供了 time 软件包来处理与时间相关的操作,但在某些情况下,开发人员需要额外的实用程序来简化与时间相关的任务。 在本篇博文中,我们将探讨一组实用工具函数,它们是 time 程序包的封装,可为操作提供便利。如果您不了解 time程序包,请考虑在深入学习高级实用程序之前参考一下相关文档。 有关基本功能,请参阅您始终需要的时间实用功能。 🎯 那么,让我们深入探讨一下如何实现。 实现 1.获取月初 一个月的开始是许多日期相关计算的基本参考点。让我们创建一个函数,将日期作为输入,并根据系统时区返回相应月份的第一天: func StartOfMonth(date time.Time) time.Time { return time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, date.Location()) } // function called StartOfMonth(time.Now()) // output 2024-01-01 00:00:00 +0530 IST 此函数将月日设置为 1,其他部分保持不变。 2.获取月末数据 相反,获取月末也同样重要。下面的函数返回给定月份最后一天的最后一秒: func EndOfMonth(date time.Time) time.Time { firstDayOfNextMonth := StartOfMonth(date).AddDate(0, 1, 0) return firstDayOfNextMonth.Add(-time.Second) } // function called EndOfMonth(time.Now()) // output 2024-01-31 23:59:59 +0530 IST 该函数利用之前定义的 StartOfMonth 函数查找下个月的第一天,然后减去一秒,得到当前月份的月底。...

January 18, 2024 · 4 min · czyt

如何获取一个Github或者gitlab用户的公钥

背景 今天无意在t上看到,然后找到这个帖子 https://stackoverflow.com/questions/16158158/what-is-the-public-url-for-the-github-public-keys How TO 获取 GitHub 可以通过下面链接 https://github.com/USER.keys https://github.com/USER.gpg 当然也可以通过github的api方式来获取 curl -i https://api.github.com/users/<username>/keys GitLab可以使用下面链接 https://gitlab.com/USER.keys https://gitlab.com/USER.gpg 使用 以github为例 curl https://github.com/<username>.keys | tee -a ~/.ssh/authorized_keys 添加完毕以后,对方就可以用ssh直接连接到你的电脑了。 这个帖子还举了bitbucket的例子 curl -i https://bitbucket.org/api/1.0/users/<accountname>/ssh-keys 延伸阅读 史上最全 SSH 暗黑技巧详解

January 17, 2024 · 1 min · czyt