美文网首页
go泛型体验

go泛型体验

作者: wwq2020 | 来源:发表于2022-03-16 19:16 被阅读0次

背景

有了泛型可以做到复用,比如sort,filter,map,reduce等常用方法,这里举个ch的例子
我们写go时候经常会进行ch的fanin,fanout操作,但是没有泛型时候,没办法写针对任何类型的(类型安全,不考虑类型安全的话可以传入interface{}然后通过反射来做到)

例子


package main

import (
    "fmt"
    "reflect"
)

func FanOut[T any](chs ...chan T) chan<- T {
    ret := make(chan T)
    recvChValue := reflect.ValueOf(ret)
    sendChValues := make([]reflect.Value, 0, len(chs))
    for _, ch := range chs {
        value := reflect.ValueOf(ch)
        sendChValues = append(sendChValues, value)
    }
    go func() {
        for {
            value, ok := recvChValue.Recv()
            for _, sendChValue := range sendChValues {
                if !ok {
                    sendChValue.Close()
                    continue
                }
                sendChValue.Send(value)
            }

            if !ok {
                return
            }
        }
    }()
    return ret
}

func FanIn[T any](chs ...chan T) <-chan T {
    ret := make(chan T)
    cases := make([]reflect.SelectCase, 0, len(chs))
    for _, ch := range chs {
        value := reflect.ValueOf(ch)
        item := reflect.SelectCase{
            Dir:  reflect.SelectRecv,
            Chan: value,
        }
        cases = append(cases, item)
    }
    go func() {
        for {
            chosen, recvValue, ok := reflect.Select(cases)
            if !ok {
                curCases := make([]reflect.SelectCase, 0, len(chs))
                for idx, each := range cases {
                    if chosen == idx {
                        curCases = append(curCases, cases[idx+1:]...)
                        break
                    }
                    curCases = append(curCases, each)
                }
                if len(curCases) == 0 {
                    close(ret)
                    return
                }

                cases = curCases
                continue
            }

            ret <- recvValue.Interface().(T)
        }
    }()
    return ret
}

func main() {
    fanInCh1 := make(chan int, 1)
    fanInCh2 := make(chan int, 1)
    fanInCh := FanIn(fanInCh1, fanInCh2)
    fanInCh1 <- 1
    fmt.Println(<-fanInCh)
    fanInCh2 <- 2
    fmt.Println(<-fanInCh)
    close(fanInCh1)
    fanInCh2 <- 3
    fmt.Println(<-fanInCh)
    close(fanInCh2)
    fmt.Println(<-fanInCh)

    fanOutCh1 := make(chan int, 1)
    fanOutCh2 := make(chan int, 1)
    fanOutCh := FanOut(fanOutCh1, fanOutCh2)
    fanOutCh <- 1
    fmt.Println(<-fanOutCh1, <-fanOutCh2)
    close(fanOutCh)
    fmt.Println(<-fanOutCh1, <-fanOutCh2)

}


相关文章

  • go泛型体验

    背景 有了泛型可以做到复用,比如sort,filter,map,reduce等常用方法,这里举个ch的例子我们写g...

  • go 泛型

    go 泛型 1. 类型参数(Type parameters) Go语言的泛型(Generic)叫做类型参数。泛型可...

  • Go 泛型初体验

    在 Go1.17 中,千呼万唤的泛型终于出来了,但又没有完全出来。在 Go1.17 的发布文档中,并没有提到泛型,...

  • 夯实 Java 基础1 - 泛型的使用与原理

    Java 泛型为我们写安全易读的通用程序提供了便利,Go 也将在 2.0 引入泛型。下面首先介绍 Java 泛型的...

  • Golang学习笔记---“泛型”的实现

    Golang学习笔记---“泛型”的实现 大家都知道,go语言中是没有泛型的,但是我们可以通过空接口的方式来实现泛...

  • Go语言 泛型

    本篇文章转载自 在go中使用"泛型" 在进入泛型的话题之前, 首先实现对int 数组切片的冒泡排序: 如你所见, ...

  • Java基础之泛型

    泛型 体验泛型 没有使用泛型时,只要是对象,不管是什么类型的对象,都可以存储进同一个集合中。使用泛型集合,可以将一...

  • JAVA泛型•约束和局限性

    为了更好地阅读体验,欢迎访问博客原文 泛型参数的限制 在Java中,实例化泛型类时泛型参数不能使用基本类型,如Li...

  • go1.18探索 -- 泛型

    go1.18终于发布了,据说支持了泛型,今天让我来一探究竟。 安装 执行如下命令 确认安装完成 泛型讲解 先看个问...

  • 泛型 & 注解 & Log4J日志组件

    掌握的知识 : 基本用法、泛型擦除、泛型类/泛型方法/泛型接口、泛型关键字、反射泛型(案例) 泛型 概述 : 泛型...

网友评论

      本文标题:go泛型体验

      本文链接:https://www.haomeiwen.com/subject/obopdrtx.html