尝试在封闭通道中插入值时避免恐慌

package main

import (
    "fmt"
    "time"
)

func fib() chan int {
    c := make(chan int)

    go func() {
        c <- 0
        c <- 1

        n, m := 0, 1
        for {
            temp := n + m
            n = m
            m = temp
            c <- m // This results in panic, when the channel is closed
        }
    }()

    return c
}

func main() {
    start := time.Now()
    var lastFib int
    c := fib()

    for i := 0; i != 1000000; i++ {
        lastFib = <-c
    }

    close(c)
    fmt.Println(lastFib)
    fmt.Println(time.Now().Sub(start))
}

In the most idiomatic way, how would one avoid the panic in the goroutine, when the channel is closed? Or should i avoid using close at all?

I'm not looking into alternative methods (such as closures) to achieve the same thing, just trying to get a better understanding of channels.

Close is a good way for the goroutine sending into a channel to signal the receiving side that you are done with this channel. The other way around (your problem) is IMHO undoable, at least direct. You could add an other channel done which signal end of duty to your fibonacci generating goroutine.

Here is a modified version of your example that uses channels in an allowed (though not necessarily sensible) way:

package main

import (
    "fmt"
    "time"
)

func fib(c chan int) {
    c <- 0
    c <- 1

    n, m := 0, 1
    for {
        temp := n + m
        n = m
        m = temp
        c <- m
        if m > 100000000 {
            close(c)
            break
        }
    }
}

func main() {
    start := time.Now()
    lastFib, newFib := 0, 0
    ok := true
    c := make(chan int)
    go fib(c)

    for {
        newFib, ok = <-c
        if !ok {
            fmt.Println(lastFib)
            break
        }
        lastFib = newFib
    }

    fmt.Println(time.Now().Sub(start))
}