[Series] Go - chan Channel

Outline

The original share basic grammar when chan has not shared the channel, this time to put it back on.

chan can be understood as a queue, follow the rules of FIFO.

Before saying chan, let's first talk about go keyword.

Add a function, you can create a thread in the back go a keyword, the function can be a function has been written, it can be anonymous function.

for example:

func main() {
    fmt.Println("main start")

    go func() {
        fmt.Println("goroutine")
    }()

    fmt.Println("main end")
}

Output:

main start
main end

Why no output goroutine?

First, we clearly thread Go language is concurrency, parallelism is not.

So, what are concurrent, parallel what is?

Concurrent different code blocks alternately performed, i.e. alternately can do different things.

Different parallel execution of code block, i.e. at the same time can do different things.

For scenes of daily life example:

You're at home reading a book, suddenly phone, and then you answer the phone, continue reading after the call is completed, which is complicated by, alternately reading and answering phones do.

If the call came, you read a book over the phone, which is parallel to do with reading and answering phones.

Coming back to the example above, why not output goroutine?

main function is a main thread, the main thread of execution because too fast, not enough time to perform sub-thread, so do not see the output.

Now let's main thread to sleep for one second, try again.

func main() {
    fmt.Println("main start")

    go func() {
        fmt.Println("goroutine")
    }()

    time.Sleep(1 * time.Second)

    fmt.Println("main end")
}

Output:

main start
goroutine
main end

now it's right.

Next, look at how to use chan.

Statement chan

// 声明不带缓冲的通道
ch1 := make(chan string)

// 声明带10个缓冲的通道
ch2 := make(chan string, 10)

// 声明只读通道
ch3 := make(<-chan string)

// 声明只写通道
ch4 := make(chan<- string)

note:

Unbuffered channels, are blocked in and out.

Buffered channel, into a length +1, the time length - 1, if the length is equal to the buffer length, then into will block.

Written chan

ch1 := make(chan string, 10)

ch1 <- "a"

Read chan

val, ok := <- ch1
// 或
val := <- ch1

Close chan

close(chan)

note:

  • close future can not write, write, there will be panic
  • Repeat close there will be panic
  • Read-only chan can not close
  • Data may also be read after the close

Examples

func main() {
    fmt.Println("main start")
    ch := make(chan string)
    ch <- "a" // 入 chan
    go func() {
        val := <- ch // 出 chan
        fmt.Println(val)
    }()
    fmt.Println("main end")
}

Output:

main start
fatal error: all goroutines are asleep - deadlock!

What? This is why, just started doing it that way?

Because the definition of an unbuffered chan, after the assignment into a blockage.

How to solve it?

Declare a buffer chan.

func main() {
    fmt.Println("main start")
    ch := make(chan string, 1)
    ch <- "a" // 入 chan
    go func() {
        val := <- ch // 出 chan
        fmt.Println(val)
    }()
    fmt.Println("main end")
}

Output:

main start
main end

Why does not output a, as before, the main thread of execution, too fast, add a second sleep, try again.

func main() {
    fmt.Println("main start")
    ch := make(chan string, 1)
    ch <- "a" // 入 chan
    go func() {
        val := <- ch // 出 chan
        fmt.Println(val)
    }()
    time.Sleep(1 * time.Second)
    fmt.Println("main end")
}

Output:

main start
a
main end

now it's right.

Look at an example:

func main() {
    fmt.Println("main start")
    ch := make(chan string)
    go func() {
        ch <- "a" // 入 chan
    }()
    go func() {
        val := <- ch // 出 chan
        fmt.Println(val)
    }()
    time.Sleep(1 * time.Second)
    fmt.Println("main end")
}

Output:

main start
a
main end

Look at an example:

func producer(ch chan string) {
    fmt.Println("producer start")
    ch <- "a"
    ch <- "b"
    ch <- "c"
    ch <- "d"
    fmt.Println("producer end")
}

func main() {
    fmt.Println("main start")
    ch := make(chan string, 3)
    go producer(ch)

    time.Sleep(1 * time.Second)
    fmt.Println("main end")
}

Output:

main start
producer start
main end

Buffered channel, if the length is equal to the buffer length, then into it will block.

Look at an example:

func producer(ch chan string) {
    fmt.Println("producer start")
    ch <- "a"
    ch <- "b"
    ch <- "c"
    ch <- "d"
    fmt.Println("producer end")
}

func customer(ch chan string) {
    for {
        msg := <- ch
        fmt.Println(msg)
    }
}

func main() {
    fmt.Println("main start")
    ch := make(chan string, 3)
    go producer(ch)
    go customer(ch)

    time.Sleep(1 * time.Second)
    fmt.Println("main end")
}

Output:

main start
producer start
producer end
a
b
c
d
main end

I went to this bar.

Recommended Reading

gRPC

Gin framework

Basics

This article Welcome forwarding, please indicate the source and author, thank you!

Guess you like

Origin www.cnblogs.com/xinliangcoder/p/11286801.html