请教一下唯一订单号的实现

我的第一种做法是直接调用一个函数(GetOutTradeNo)返回唯一的订单号,订单号通过redis缓存1秒,如果存在缓存中就重新随机一个,然后我启动了10个goroutine测试了一下,发现还是会产生重复的订单号

接着我用channel来实现,这是我第一次用channel,所以我就按照我自己的一些理解实现了,启动一个goroutine来管理订单的生成,调用GetOutTradeNo()传递一个chan string过去,接收到之后就开始生成订单号,生成完毕传回去,启动10个goroutine之后的确是10个不一样的订单号,但是多测试几次就发现有时候生成的只有5个订单号或者9个订单号等,好吧,估计就是稍微执行慢一点,错过了一些chan string
大致代码是这样

var outTradeNoQueueChannel chan chan string

// GetOutTradeNo 获取唯一订单号
func GetOutTradeNo() string {
    str := make(chan string)
    outTradeNoQueueChannel <- str

    result := <-str
    fmt.Println(result)

    return result
}

func OutTradeNoThink() {
    outTradeNoQueueChannel = make(chan chan string, 1)
    for {
        select {
        case str := <-outTradeNoQueueChannel:
            .....
            str <- result
        }
    }
}

最后我加了一个数组来实现,测试几次都达到预期,然后我启动了1万个goroutine,令人绝望是一堆莫名的错误

var outTradeNoQueueChannel chan chan string
var outTradeNoQueue []chan string

// GetOutTradeNo 获取唯一订单号
func GetOutTradeNo() string {
    str := make(chan string)
    outTradeNoQueueChannel <- str
    result := <-str
    fmt.Println(result)
    return result
}
func OutTradeNoThink() {
    outTradeNoQueueChannel = make(chan chan string, 1)
    for {
        select {
        case str := <-outTradeNoQueueChannel:
            outTradeNoQueue = append(outTradeNoQueue, str)
        default:
            if len(outTradeNoQueue) == 0 {
                time.Sleep(time.Millisecond * 100)
                continue
            }

            var str chan string
            str, outTradeNoQueue = outTradeNoQueue[0], outTradeNoQueue[1:]
            ......
            str <- result
        }
    }
}

以下是产生的错误,比如[chan receive] [chan send] [select]之类的错误

goroutine 7696 [chan receive]:
app/pay.GetOutTradeNo(0x0, 0x0)
    Z:/avalon-hk/avalon_service/src/app/pay/common.go:26 +0x111
main.main.func1(0xc04216e030)
    Z:/avalon-hk/avalon_service/src/app/main.go:45 +0x2d
created by main.main

goroutine 1781 [semacquire]:
sync.runtime_SemacquireMutex(0xc0420600a4)
        C:/Go/src/runtime/sema.go:62 +0x3b
sync.(*Mutex).Lock(0xc0420600a0)
        C:/Go/src/sync/mutex.go:87 +0xa4
os.(*File).write(0xc04205e008, 0xc0421a13a0, 0x12, 0x20, 0x0, 0x0, 0x0)
        C:/Go/src/os/file_windows.go:365 +0x63
os.(*File).Write(0xc04205e008, 0xc0421a13a0, 0x12, 0x20, 0xc04309e820, 0xc042d9af98, 0xc04309e820)
        C:/Go/src/os/file.go:142 +0x7d
fmt.Fprintln(0xab1cc0, 0xc04205e008, 0xc0430adf20

好吧,其实写完这段代码发现还是没有解决刚才根本的问题
刚用golang一个星期,还不是很了解,不喜勿喷哈 :)
不知道还有没有什么高超的做法

共 1 个回复