在学习 Go 的泛型,写了个模拟 async/await 的小工具,写的过程中发现个问题

2022-08-30 21:23:40 +08:00
 rrfeng

谁能看出来问题在哪里 #狗头

代码:

package future

import (
        "context"
)

type Future[T any] interface {
        Await() (T, error)
        Cancel()
}

type future[T any] struct {
        ret    chan result[T]
        ctx    context.Context
        cancel context.CancelFunc
}

type result[T any] struct {
        dat T
        err error
}

func Async[T any](fn func() (T, error)) Future[T] {
        return AsyncWithContext(context.Background(), fn)
}

func AsyncWithContext[T any](ctx context.Context, fn func() (T, error)) Future[T] {
        c := make(chan result[T], 1)
        fctx, cancel := context.WithCancel(ctx)

        go func() {
                ret, err := fn()
                c <- result[T]{dat: ret, err: err}
        }()
        return &future[T]{ret: c, ctx: fctx, cancel: cancel}
}

func (f *future[T]) Await() (T, error) {
        var result result[T]

        select {
        case <-f.ctx.Done():
                result.err = f.ctx.Err()
        case ret := <-f.ret:
                result = ret
        }

        f.cancel()
        return result.dat, result.err
}

func (f *future[T]) Cancel() {
        f.cancel()
}

用法是:

f := future.Async(myfunc)
// 去干其他事
result, err := f.Await()
2090 次点击
所在节点    Go 编程语言
24 条回复
rrfeng
2022-09-02 17:24:22 +08:00
@pastor 真搞不懂哪里来的优越感和这么喜欢批判别人
pastor
2022-09-02 19:19:32 +08:00
@rrfeng
这不是优越感,只是我这个人说话比较实在并且直接,你听了可能会不舒服而已。
至于为什么这样不懂得客气,是因为有过太多因为客气委婉、别人反倒以为自己没问题,所以我不想再客气了,有问题就尖酸刻薄地指出,至少对于技术本身,是中肯切实的

批判跟优越感也没有直接关系。
批判纯粹是因为你做的这个语法糖是一种倒退,如果没有其他人参与讨论我就不会来留言了,但是看到其他人也参与了讨论并且没有意识到这种语法糖是倒退,这就可能导致有更多人被误导。

同样有一些其他人参考其他语言做一些对于 go 而言是倒退的东西,如果力所能及,我也都会献上一些建议不要这样做的刻薄说辞

但我不只是空口乱喷,讲了一些点的,OP 要是能静下心来回到技术本身,对自己是有好处的

OP 不要纠结我的说话方式,你就当我是个没礼貌的小学生无视我的不客气好了。对其他人也一样,每个人隔三差五总会遇到让自己不舒服的人,我们没法改变环境,但是能适应环境,只要不是切实伤害,自己内心强大就无所谓别人客气不客气了

已经好些人说我刻薄之类的了,我自己也知道并且欣赏自己的刻薄。刻薄并不是什么坏事情,这世界,总是需要有一些刻薄的人的

良药苦口,忠言逆耳,认真思考技术就行了,共勉
pastor
2022-09-02 19:20:51 +08:00
@rrfeng “真搞不懂哪里来的优越感和这么喜欢批判别人”

补充一点,不是批判 OP 你这个人,是说这个语法糖这个实现
rix
2022-09-09 16:22:36 +08:00
你需要 [tomb]( https://pkg.go.dev/gopkg.in/tomb.v2)

可以看這篇介紹: http://blog.labix.org/2011/10/09/death-of-goroutines-under-control

你似乎注意到了 Go Routine 的一大痛點,也就是沒有返回值和錯誤信息。

Tomb 提供了一個描述異步過程生命週期的類型,可以很好地管理異步生命週期。

但是 Tomb 仍然只是最基礎的生命週期描述符,它本身不具備多個異步生命週期的函數式組合。

因此我寫了 [go-rx]( https://github.com/go-rx/rx) 你可以看看,是基於 Tomb 的,結合了 Rx ( Reactive Extension )異步函數式語言的異步生命週期管理和組合用的庫。你可以併發多個 Go Routine 然後合併它們的返回值和錯誤信息,可以使用函數式的語言進行 piping 等等。

可以看我這篇文章瞭解更多: https://dev.to/rix/rx-with-go-generics-2fl6

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/876569

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX