Skip to content

channel 题目 #53

Open
Open
@JasonJe

Description

@JasonJe
  1. 下面代码会触发异常吗
func main() {
    runtime.GOMAXPROCS(1)
    int_chan := make(chan int, 1)
    string_chan := make(chan string, 1)
    int_chan <- 1
    string_chan <- "hello"
    select {
    case value := <-int_chan:
        fmt.Println(value)
    case value := <-string_chan:
        panic(value)
    }
}

解析:可能触发异常,也可能不会触发异常。

  1. channel特性说明
  • 给一个 nil channel 发送数据,造成永远阻塞;

  • 从一个 nil channel 接收数据,造成永远阻塞;

  • 给一个已经关闭的 channel 发送数据,引起 panic

  • 从一个已经关闭的 channel 接收数据,如果缓冲区中为空,则返回一个零值,缓冲区不为空,返回已缓冲数据;

  • 无缓冲的channel是同步的,而有缓冲的channel是非同步的。

  1. 下面代码输出什么
func main() {
    ch := make(chan int, 100)
    // A
    go func() {              
        for i := 0; i < 10; i++ {
            ch <- i
        }
    }()
    // B
    go func() {
        for {
            a, ok := <-ch
            if !ok {
                fmt.Println("close")
                return
            }
            fmt.Println("a: ", a)
        }
    }()
    close(ch)
    fmt.Println("ok")
    time.Sleep(time.Second * 10)
}

解析:当 A 协程还没起时,主协程已经将 channel 关闭了,当 A 协程往关闭的 channel 发送数据时会 panicpanic: send on closed channel

  1. 下面的代码有什么问题
func Stop(stop <-chan bool) {
    close(stop)
}

解析:有方向的 channel 不可以被关闭。

  1. 下面代码输出什么
func main() {
    var ch chan int
    select {
    case v, ok := <-ch:
        println(v, ok)
    default:
        println("default") 
    }
}

输出:default

解析:chnil,读写都会阻塞。

  1. 下面的代码输出什么
var o = fmt.Print

func main() {
    c := make(chan int, 1)
    for range [3]struct{}{} {
        select {
        default:
            o(1)
        case <-c:
            o(2)
            c = nil
        case c <- 1:
            o(3)
        }
    }
}

输出:321

解析:第一次循环,写操作已经准备好,执行 o(3),输出 3;第二次,读操作准备好,执行 o(2),输出 2 并将 c 赋值为 nil;第三次,由于 cnil,走的是 default 分支,输出 1

  1. 下面的代码有什么问题
type data struct {
    sync.Mutex
}

func (d data) test(s string)  {
    d.Lock()
    defer d.Unlock()

    for i:=0;i<5 ;i++  {
        fmt.Println(s,i)
        time.Sleep(time.Second)
    }
}

func main() {
    var wg sync.WaitGroup
    wg.Add(2)
    var d data

    go func() {
        defer wg.Done()
        d.test("read")
    }()

    go func() {
        defer wg.Done()
        d.test("write")
    }()

    wg.Wait()
}

解析:锁失效。将 Mutex 作为匿名字段时,相关的方法必须使用指针接收者,否则会导致锁机制失效。

修复代码:

type data struct {
    *sync.Mutex     // 嵌入 *Mutex 来避免复制的问题,但是需要初始化
}

func (d data) test(s string) {    // 值方法
    d.Lock()
    defer d.Unlock()

    for i := 0; i < 5; i++ {
        fmt.Println(s, i)
        time.Sleep(time.Second)
    }
}

func main() {

    var wg sync.WaitGroup
    wg.Add(2)

    d := data{new(sync.Mutex)}   // 初始化

    go func() {
        defer wg.Done()
        d.test("read")
    }()

    go func() {
        defer wg.Done()
        d.test("write")
    }()

    wg.Wait()
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    GoGolang

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions