脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|shell|

服务器之家 - 脚本之家 - Golang - Go不能写,但是可以用Rust写的三段代码!

Go不能写,但是可以用Rust写的三段代码!

2024-03-08 14:02coding到灯火阑珊 Golang

在这篇文章中,要分享的例子不仅仅是假设,它们来自于工作中的真实案例,在这些例子中,Go的局限性无法实现所需的解决方案。声明:这里的区别并不在于Rust代码比Go代码更正确或更快。

在这篇文章中,要分享的例子不仅仅是假设,它们来自于工作中的真实案例,在这些例子中,Go的局限性无法实现所需的解决方案。声明:这里的区别并不在于Rust代码比Go代码更正确或更快。

1.读取线程的ID

记录当前线程的ID,或者在Go的情况下,记录协程ID,是非常有用的。它明确了哪个线程正在做什么。如果没有这些信息,每个线程的活动就会交织在一个日志文件中,因此很难跟踪单个执行流。

在Rust中,获取线程id就像这样简单:

let id = thread::current().id();

然而,Go并不公开协程id。Go故意不公开协程id,以阻止开发人员对线程本地存储进行编程。对于想要理解日志的开发人员必须求助于其他方法来检索该信息。

2.单个Select语句中的Case优先级排序

Go在select-case语句(等待多个通道操作)中随机选择所有就绪中的一个。如果准备好了多个case,并且希望在单个select语句中优先执行一个case,则不行。

在下面的代码中,nReady1在统计上等于nReady2。

func main() {
    ready1 := make(chan struct{})
    close(ready1)
    ready2 := make(chan struct{})
    close(ready2)

    nReady1 := 0
    nReady2 := 0
    N := 10_000
    for i := 0; i < N; i++ {
        select {
        case <-ready1:
           nReady1++
        case <-ready2:
           nReady2++
        }
    }
    fmt.Println("nReady1:", nReady1)
    fmt.Println("nReady2:", nReady2)
}

执行结果:

nReady1: 4943
nReady2: 5057

必须使用嵌套的select语句(带有默认值)来实现优先级。

select {
    case <-ready1:
       nReady1++
    default:
       select {
          case <-ready1:
             nReady1++
          case <-ready2:
             nReady2++
       }
}

然而,Rust的异步运行时Tokio允许在单个select语句中使用biased关键字设置优先级顺序。

在下面的例子中,按照它们在代码中出现的顺序排列优先级。

use tokio::sync::mpsc;
use tokio::select;

#[tokio::main]
async fn main() {
    let (tx1, mut rx1) = mpsc::channel::<()>(1);
    drop(tx1);
    let (tx2, mut rx2) = mpsc::channel::<()>(1);
    drop(tx2);

    let mut n_ready1 = 0;
    let mut n_ready2 = 0;
    let n = 10_000;
    for _ in 0..n {
        select! {
            biased; // 按出现的顺序优先处理已准备好的case
            _ = rx1.recv() => {
                n_ready1 += 1;
            },
            _ = rx2.recv() => {
                n_ready2 += 1;
            },
        }
    }

    println!("n_ready1: {}", n_ready1);
    println!("n_ready2: {}", n_ready2);
}

执行结果:

n_ready1: 10000
n_ready2: 0

Rust使用单个select语句实现了对case的优先级排序。

3.具有指针和值接收器的泛型类型

在Go中,你想为类型参数S定义一个类型约束,它实现了两个方法:

type S struct{}

func (s S) M()  {}
func (s *S) P() {}

不幸的是,不可能用单个类型约束指定这两个方法。必须使用两个单独的类型参数,每个类型参数都有自己的约束,然后将它们链接到函数f中。首先,定义T受Mer接口类型的约束。然后,将PT定义为受Per[T]接口类型约束,并引用第一个T。这看起来很复杂,并不直观。

type Per[T any] interface {
    P()
    *T // 非接口类型约束元素
}

type Mer interface {
    M()
}

func f[T Mer, PT Per[T]](t T) {
    PT(&t).P()
    t.M()
}

在Rust中,解决方案很简单。定义一个单独的trait:MyTrait,然后将它用作f中的一个trait绑定。

trait MyTrait {
    fn M(&self);
    fn P(&mut self);
}

struct S;

impl MyTrait for S {
     fn M(&self) {}
    fn P(&mut self) {}
}

fn f<T: MyTrait>(t: &mut T) {
    t.M();
    t.P();
}

总结

Rust通过在编译时而不是运行时检测错误来确保可靠性,实现高性能,并且具有一定程度的表达性,使其可以编写其他语言无法编写的代码。

原文地址:https://mp.weixin.qq.com/s/3GCIoBJ8oSmI5XO6g-lsmQ

延伸 · 阅读

精彩推荐
  • GolangGo 语言字符串使用方式与技巧

    Go 语言字符串使用方式与技巧

    本文我们介绍 Go 语言中字符串的使用方式,包括类型转换、字符串操作、字符串拼接。除了使用标准库 strconv​ 进行字符串类型转换之外,读者朋友们也可...

    Golang语言开发栈11412023-12-11
  • Golanggo语言中[]*int和*[]int的具体使用

    go语言中[]*int和*[]int的具体使用

    本文主要介绍了go语言中[]*int和*[]int的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面...

    别人家的孩子zyh8652023-04-20
  • GolangGo语言--切片(Slice)详解

    Go语言--切片(Slice)详解

    这篇文章主要介绍了Go语言--切片(Slice),Go 语言切片是对数组的抽象,下面文章小编将为大家详细介绍该内容,需要的朋友可以参考下,希望对你有所帮...

    归子莫11012021-11-19
  • Golanggolang语言中wasm 环境搭建的过程详解

    golang语言中wasm 环境搭建的过程详解

    将 golang 打包为 WASM,通常有两种打包方式,一种是 golang 自带的,另外是使用 tinygo ,接下来通过本文给大家介绍golang语言中wasm 环境搭建的过程,感兴趣的...

    shushushu6382021-12-01
  • GolangGo 使用xorm操作mysql详情

    Go 使用xorm操作mysql详情

    这篇文章主要介绍了Go 使用xorm操作mysql详情,golang orm 库 xorm 的使用和项目结构。更多详细neural,需要的小伙伴可以参考下面文章内容...

    运维派7742022-08-29
  • GolangUber Go 出了个静态分析工具 NilAway,还挺实用!

    Uber Go 出了个静态分析工具 NilAway,还挺实用!

    今天针对 Go 里最常见的 nil 指针问题进行了静态分析工具 NilAway 的分享。虽然目前该工具还没有正式的生产可用。...

    脑子进煎鱼了4692024-01-03
  • Golang手把手带你走进Go语言之运算符解析

    手把手带你走进Go语言之运算符解析

    这篇文章主要介绍了手Go语言之运算符解析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    我是小白呀7992021-09-19
  • GolangGolang数据结构性能优化实践

    Golang数据结构性能优化实践

    如果你有Golang开发经验,一定定义过struct类型。 但可能你不知道,通过简单的重新排序struct字段,可以极大提高Go程序的速度和内存使用效率! 是不是难以...

    DeepNoMind10722024-01-02