lifei6671 / interview-go

golang面试题集合
Apache License 2.0
5.06k stars 898 forks source link

交替打印数字字母的另外一种实现方法 #2

Open Momo733 opened 6 years ago

Momo733 commented 6 years ago
package main

import (
    "fmt"
    "runtime"
    "sync"
)

const N = 28

func main() {
    runtime.GOMAXPROCS(1)
    wg := &sync.WaitGroup{}
    wg.Add(N)
    for i := 0; i < N; i++ {
        go func(m int) {
            defer wg.Done()
            fmt.Printf(`%d%d`,m+1,m+2)
            runtime.Gosched()
        }(i)
        go func(m int) {
            defer wg.Done()
            if m == 26 {
                runtime.Goexit()
            }
            fmt.Printf(`%c%c`, 'A'+m, 'A'+m+1)
        }(i)
        i = i + 1
    }
    wg.Wait()
}
Momo733 commented 6 years ago

对于这种的解决方法,我一直有一个问题,为什么最后的goruntine会最先执行,下面是代码:

package main

import (
    "runtime"
    "sync"
    "fmt"
)

const N = 10

func main() {
    runtime.GOMAXPROCS(1)
    wg := &sync.WaitGroup{}
    wg.Add(N*2)
    for i := 0; i < N; i++ {
        m := i
        go func(m int) {
            defer wg.Done()
            fmt.Print(m)
        }(m)
        go func(m int) {
            defer wg.Done()
            runtime.Gosched()
            fmt.Printf(`%c`,'A'+m)
        }(m)
    }
    wg.Wait()
}

结果是J0123456789ABCDEFGHIJ居然是最先打印的,大佬知道原因么,谢谢!

lifei6671 commented 6 years ago

貌似是golang的调度器并不能保证协程是顺序执行的。

tlightsky commented 5 years ago

也贴一个我的: https://gist.github.com/tlightsky/a67e3ee1360e79432478d0baa4a3cab6

linture commented 5 years ago
package main
import (
  "fmt"
)

// POINT: communicate between goroutines by channel

//使用两个 goroutine 交替打印序列,一个 goroutine 打印数字, 另外一个 goroutine 打印字母, 最终效果如下:
//12AB34CD56EF78GH910IJ1112KL1314MN1516OP1718QR1920ST2122UV2324WX2526YZ2728
func AlterPrint(){
  letter, number := make(chan bool), make(chan bool)
  letterDone := make(chan bool)
  go func() {
    i := 1
    for {
      select{
        case <-number: {
          fmt.Print(i)
          i++
          fmt.Print(i)
          i++
          letter <- true
          break
        }
        default: {
          break
        }
      }

    }
  }()

  go func(){
    i := 'A'
    for {
      if i > 'Z' {
        letterDone <- true
        return
      }
      select{
        case <-letter: {
          fmt.Print(string(i))
          i++
          fmt.Print(string(i))
          i++
          number <- true
          break
        }
        default: {
          break
        }
      }
    }
  }()
  number <- true
  <- letterDone
}
dchaofei commented 5 years ago
    letter, number := make(chan struct{}), make(chan struct{})
    var wg sync.WaitGroup
    wg.Add(2)
    go func() {
        defer wg.Done()
        i := 1
        pr := func() {
            fmt.Print(i)
            i++
        }
        for {
            _, ok := <-number
            if !ok {
                close(letter)
                break
            }
            pr()
            pr()
            letter <- struct{}{}
        }
    }()
    go func() {
        defer wg.Done()
        str := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        length := len(str)

        i := 0
        pr := func() bool {
            if i == length {
                return false
            }
            fmt.Print(string(str[i]))
            i++
            return true
        }
        for {
            _, ok := <-letter
            if !ok || !pr() || !pr() {
                break
            }
            number <- struct{}{}
        }
        close(number)
    }()
    number <- struct{}{}
    wg.Wait()
ghost commented 3 years ago

贴一个俺的😛

func main() {
    letter, number := make(chan int, 1), make(chan int, 1)
    var wg sync.WaitGroup
    wg.Add(2)
    defer func() {
        close(letter)
        close(number)
    }()

    go func() {
        for {
            select {
            case num := <-number:
                if num >= 13 {
                    wg.Done()
                    return
                }
                fmt.Printf("%d%d", 2*num+1, 2*num+2)
                letter <- num
            }
        }
    }()
    go func() {
        for {
            select {
            case let := <-letter:
                fmt.Printf("%c%c", 'A'+2*let, 'A'+2*let+1)
                number <- let + 1
                if let >= 12 {
                    wg.Done()
                    return
                }
            }
        }
    }()
    number <- 0
    wg.Wait()
}
NightmareZero commented 2 years ago
package main

import (
  "fmt"
  "runtime"
  "sync"
)

const N = 28

func main() {
  runtime.GOMAXPROCS(1)
  wg := &sync.WaitGroup{}
  wg.Add(N)
  for i := 0; i < N; i++ {
      go func(m int) {
          defer wg.Done()
          fmt.Printf(`%d%d`,m+1,m+2)
          runtime.Gosched()
      }(i)
      go func(m int) {
          defer wg.Done()
          if m == 26 {
              runtime.Goexit()
          }
          fmt.Printf(`%c%c`, 'A'+m, 'A'+m+1)
      }(i)
      i = i + 1
  }
  wg.Wait()
}

总共这么一个需求犯得着在for循环里面放goroutine么,这个不是禁忌么