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

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

在 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 类型包装了我们想要发回的任何内容。正如您在上面看到的,我们还可以单独返回一个字符串(切片)。...

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) => { ....

在 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 格式相互转换:...

转换数字到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# 实现代码:...

关于七牛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代码做了部分修改...

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 函数查找下个月的第一天,然后减去一秒,得到当前月份的月底。...

如何获取一个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 暗黑技巧详解

Google Service Weaver中文文档[机翻]

本文为 Service Weaver 文档的机器翻译+细节微调。 Service Weaver是什么 ? Service Weaver 是一个用于编写、部署和管理分布式应用程序的编程框架。您可以在计算机上本地运行、测试和调试 Service Weaver 应用程序,然后使用单个命令将该应用程序部署到云。 $ go run . # Run locally. $ weaver ssh deploy weaver.toml # Run on multiple machines. $ weaver gke deploy weaver.toml # Run on Google Cloud. $ weaver kube deploy weaver.toml # Run on Kubernetes. Service Weaver 应用程序由许多组件组成。组件被表示为常规的 Go 接口,组件之间通过调用这些接口定义的方法进行交互。这使得编写 Service Weaver 应用程序变得容易。您不必编写任何网络或序列化代码;你只要写 Go 就可以了。 Service Weaver 还提供用于日志日志、指标、跟踪、路由、测试等的库。 您可以像运行单个命令一样轻松地部署 Service Weaver 应用程序。在幕后,Service Weaver 将沿着组件边界Profile您的二进制文件,从而允许不同的组件在不同的计算机上运行。 Service Weaver 将为您复制、自动缩放和共同定位这些分布式组件。它还将代表您管理所有网络详细信息,确保不同的组件可以相互通信,并且客户端可以与您的应用程序通信。...

一些使用go-fyne的笔记

界面交互 中文字体设置 查阅相关资料,有下面几种解决方案,下面来依次说明。 环境变量 可以通过指定 FYNE_FONT 环境变量来使用替代字体 使用字体bundle 安装fyne工具,使用下面的命令: go install fyne.io/fyne/v2/cmd/fyne@latest 准备好要使用的字体,我们这里使用miSans,使用下面命令 fyne bundle MiSans-Normal.ttf > bundle.go 然后创建一个theme package tinytheme import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/theme" "fyneHello/fontRes" "image/color" ) type ChineseTheme struct{} var _ fyne.Theme = (*ChineseTheme)(nil) func (m *ChineseTheme) Font(s fyne.TextStyle) fyne.Resource { return fontRes.ResourceMiSansTTF } func (*ChineseTheme) Color(n fyne.ThemeColorName, v fyne.ThemeVariant) color.Color { return theme.DefaultTheme().Color(n, v) } func (*ChineseTheme) Icon(n fyne.ThemeIconName) fyne.Resource { return theme.DefaultTheme().Icon(n) } func (*ChineseTheme) Size(n fyne....