Go 1.24 Release Notes

Introduction to Go 1.24 The latest Go release, version 1.24, arrives six months after Go 1.23. Most of its changes are in the implementation of the toolchain, runtime, and libraries. As always, the release maintains the Go 1 promise of compatibility. We expect almost all Go programs to continue to compile and run as before. Changes to the language Go 1.24 now fully supports generic type aliases: a type alias may be parameterized like a defined type. See the language spec for details. For now, the feature can be disabled by setting GOEXPERIMENT=noaliastypeparams; but the aliastypeparams setting will be removed for Go 1.25. ...

二月 14, 2025 · 20 分钟 · anoya

Rust版本更新: 1.84.1

1.84.1修复了在1.84.0中引入的一些回归问题: 修复ICE 132920中的重复箱诊断。 修复增量编译过程中的错误,涉及到重叠实现。 修复与下一代特征求解器相关的慢速编译。 修复LLVM的位置判别符值限制超过时的debuginfo。 此外,还包括一些从源代码构建Rust时的修复: 只有在LLVM工具被启用时才尝试分发llvm-objcopy。 为非Git来源添加配置覆盖选项。 在拷贝它们之前,解除LLVM工具二进制文件的符号链接。 使它可能使用ci-rustc在tarball源上。

二月 1, 2025 · 1 分钟 · anoya

Rust常用设计模式

设计模式的使用,是对开发者的考验。比如说在 Golang 中最常用的是工厂模式,创建模块时,以 Struct 为基础,常命名为 NewXX 开头发的方法作为工厂模式。而在 Rust 中,常用的则是建造模式(builder),由此来创建某一模块或功能的集合。 另外在 Rust 中独有的模式,例如 Drop Builder Builder1 is a creational design pattern that lets you construct complex objects step by step. The pattern allows you to produce different types and representations of an object using the same construction code. 建造者是一个创造性的设计模式,让你一步步构建复杂的对象。模式允许你使用相同的结构代码构建不同的类型和表现对象。 例子使用Box Builder,构建不同尺寸的盒子,通过链式调用设置不同的盒子属性 struct Box { width: u32, height: u32, } struct BoxBuilder { width: Option<u32>, height: Option<u32>, } impl BoxBuilder { fn new() -> Self { BoxBuilder { width: None, height: None, } } fn default() -> Self { BoxBuilder { width: Some(30), height: Some(30), } } fn set_width(mut self, width: u32) -> Self { self.width = Some(width); self } fn set_height(mut self, height: u32) -> Self { self.height = Some(height); self } fn build(self) -> Box { let width = self.width.unwrap(); let height = self.height.unwrap(); Box { width, height } } } fn main() { let box1: Box = BoxBuilder::new().set_height(20).set_width(10).build(); println!( "the box1 width is {}, height is {}.", box1.width, box1.height ); let box2: Box = BoxBuilder::default().build(); println!( "the box2 width is {}, height is {}.", box2.width, box2.height ); } output: ...

一月 24, 2025 · 4 分钟 · anoya

frp内网穿透搭建

研究frp笔记,内网穿透,基于Ubuntu20.04的frp安装 frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。 一、下载frp 在github地址:https://github.com/fatedier/frp Release:https://github.com/fatedier/frp/releases 以下是在服务器中的操作 # 创建文件夹 mkdir frp && cd frp # 下载frp0.38版本(如果下载速度慢,可采用本地下载后,通过ftp传输到服务器中) wget https://github.com/fatedier/frp/releases/download/v0.38.0/frp_0.38.0_linux_amd64.tar.gzß # 解压指定目录 tar -zxvf frp_0.38.0_linux_amd64.tar.gz cd frp_0.38.0_linux_amd64 当前所在目录即为frp 二、运行frps frp的服务端,需在服务器中运行 修改配置文件 根据frps_full.ini选出自己所需要的配置 常用配置信息: frps.ini [common] ; 绑定frps地址 bind_addr = 0.0.0.0 ; frps端口号 bind_port = 7000 ; 仪表盘配置 dashboard_addr = 0.0.0.0 dashboard_port = 7500 ; 仪表盘账号密码 dashboard_user = admin dashboard_pwd = admin ; 当前server端的日志输出文件 log_file = ./frps.log ; 日志等级 trace, debug, info, warn, error log_level = info ; 日志保存最大天数 log_max_days = 3 ; 验证方法 authentication_method = token ; token验证 token = 12345678 ; if you want to support virtual host, you must set the http port for listening (optional) ; Note: http port and https port can be same with bind_port ; 虚拟http端口 vhost_http_port = 8080 ; vhost_https_port = 443 ; 域名设置 subdomain_host = yother.cn 将frps.ini保存在与frps同级目录下,运行命令 ...

一月 24, 2025 · 2 分钟 · anoya

互斥锁与自旋锁

在现实生活中,锁的作用无非是将物品关起来,防止被他人进入等。而在程序中锁的概念也是如此,当同一个内存地址被同时访问时,会造成数据竞争,意思是不知道当前变量被谁所操作,所以引入了锁的概念,当有人来访问时,对此变量加上一把锁来防止其他对象对其访问,这样才会更安全的使用变量做操作。现实中锁的种类有多种,比如物理锁、指纹锁等。在程序中亦是如此,这里大类氛围两种,互斥锁和自旋锁。 1. 数据竞争(Data Race)1 Data Race 又称 Race Condition。它旨在描述一个系统或者进程的输出依赖于不受控制的事件出现顺序或者出现时机。此词源自于两个信号试着彼此竞争,来影响谁先输出。 计算机为了提高性能,出现了多线程和多进程,增加了执行并行能力,但是在保持数据一致上就需要外力来维持。而造成这一原因的就是数据竞争,多个执行者对一个事物的操作。最为常见的例子是在银行存取款,如果付款存在多个交易时较为容易出现这类问题。 事例 如果你银行卡中有余额 1000 元,当你同时购买两个售价分别是 100 和 200 元的商品时,在银行账户中的操作可能是这样的 1000 -100 = 900 // 购买 100 元商品时扣款 900 - 200 = 700 // 购买成功第一个商品后,扣款 200 元商品 1000 - 200 = 800 // 购买 200 元善品时扣款 余额可能是这三种,因为在同时付款的时候,你不知道哪个扣款是先处理操作。所以会出现上述情况,按理说付款完成后余额剩余 700 才是正确的,但是为什么会出现这种情况,是因为出现了数据竞争,但进行扣款操作时候,两者都拿到了总额为 1000 的进行扣除,其中有一方肯定错误的扣除处理。 # 使用Golang实现 package main import ( "fmt" "sync" ) // 余额 var Balance uint = 1000 // wg var wg sync.WaitGroup // 消费行为 func consume(money uint) uint { defer wg.Done() Balance -= money return Balance } func do() { defer wg.Wait() goods := [2]uint{100, 200} // 同时有两款交易进行中 for i := range goods { wg.Add(1) go func(i int) { fmt.Printf("Current balance is: %v\n", consume(goods[i])) }(i) } } 运行函数do(),得到输出为: ...

一月 24, 2025 · 6 分钟 · anoya