• slice 或 map 元素是 struct 的,literal 元素类型可以省略,例如:里层的 ListMenu 和 AddMenu 可以省略。 参考:https://golang.org/ref/spec#Composite_literals (关键词 elide)

  • 南丁格尔 (Nightingale)这名字起得好。

  • But why?

  • go get 问题 at 2020年03月19日

    需要学习 Go Modules 的基本用法: https://blog.golang.org/using-go-modules

  • 看到 “6 years ago” 和那么少的 stars,我就绝望了。。。

  • lol

  • 补充几句:

    • (伪)随机数本质上没办法并发产生(具体原因涉及伪随机数生成的原理):rand.Rand 下的方法都不是并发安全的,所以 rand.Intn 里有锁,所以并发 “分别产生” 随机数是个伪问题
    • 输出到标准输出,os.Stdout.Write 里也有锁,所以并发 “各自输出” 也是伪问题
    • 按照题目要求 “分别产生” 且 “各自输出”:即不允许 goroutine 之间交流,严格来说无解(也可以理解为原题陈述要求不严谨)

    放松题目要求:

    • 有效率且有实际意义的实现,要分成 master,map,reduce 三个阶段:master 统一产生随机数序列,分发到多个 map worker,做一些业务逻辑,再统一到 reduce worker 做排序。如果数量太大,可以做 sharding 分配到多个 reduce worker,结果由各个 reduce worker 分段排序
    • 不管有没有效率,允许 goroutine 之间来来回回的用 channel 通信,也可以拼凑出来一个所谓答案
    • 还有一种简单有趣的 “解法”,如下

    -----之前的回复-----

    没有排序,各自输出本质上不能保证顺序,可以这么玩儿出来,但是有实际意义么?这不是脑筋急转弯么?

    package main
    
    import (
        "fmt"
        "math/rand"
        "sync"
        "time"
    )
    
    func outputRand(wg *sync.WaitGroup) {
        defer wg.Done()
        i := rand.Intn(100)
        time.Sleep(time.Duration(i) * time.Millisecond)
        fmt.Println(i)
    }
    
    func main() {
        rand.Seed(time.Now().UnixNano())
        var wg sync.WaitGroup
        for i := 0; i < 10; i++ {
            wg.Add(1)
            go outputRand(&wg)
        }
        wg.Wait()
    }
    

    解完了才想起来貌似几年前见过这道题,old 。。。

  • 这个位置比较符合我们对 Go 的认知,排在 Go 前面的都是久经考验的大众化语言。 Go 正在进入通用语言的第一梯队。

  • 这个问题本应留给自己调查先:https://daringfireball.net/projects/markdown/syntax#p

    1. 以上代码并发读写变量没加任何同步,是错误的写法(虽然不影响问题本身的讨论)
    2. Go language spec 没有规定 goroutine 应该如何调度,所以在代码逻辑没问题的前提下 goroutine 卡住是 Go 1.13 及以前版本 runtime 实现上的局限,而不是语言层面的问题
    3. 这个问题在 Go 1.14 已经得到了解决

    以下例子在 go1.14 darwin/amd64 可以跑完,但是在 go1.13.8 会卡住。在适当的位置添加 runtime.Gosched() 可以缓解 1.13 之前的问题。

    package main
    
    import (
        "fmt"
        // "runtime"
        "sync/atomic"
    )
    
    func main() {
        n := int64(0)
        go func() {
            for i := 0; ; i++ {
                v := atomic.LoadInt64(&n)
                fmt.Println(v)
                atomic.StoreInt64(&n, v+1)
            }
        }()
    
        prev := atomic.LoadInt64(&n)
        dupCount := 0
        for {
            cur := atomic.LoadInt64(&n)
            if cur == prev {
                dupCount++
                if dupCount > 250000 {
                    // uncomment this line to run smoothly before Go 1.14
                    // runtime.Gosched()
                }
            }
            if cur > 1000000 {
                break
            }
        }
    }