有以下三種迭代的寫法:python
假設實現迭代從[2, max],打印出偶數。函數
func printEvenNumbers(max int) { if max < 0 { log.Fatalf("'max' is %d, should be >= 0", max) } for i := 2; i <= max; i += 2 { fmt.Printf("%d\n", i) } }
// 將迭代的數值傳遞到回調函數 func printEvenNumbers(max int) { err := iterateEvenNumbers(max, func(n int) error { fmt.Printf("%d\n", n) return nil }) if err != nil { log.Fatalf("error: %s\n", err) } } // 實際的迭代的結果,接受一個回調函數,由回調函數處理 func iterateEvenNumbers(max int, cb func(n int) error) error { if max < 0 { return fmt.Errorf("'max' is %d, must be >= 0", max) } for i := 2; i <= max; i += 2 { err := cb(i) if err != nil { return err } } return nil }
// Next()方法放在for循環體以後,經過返回布爾值來控制是否迭代完畢 func (i *EvenNumberIterator) Next() bool // Value()方法返回當次迭代的值 func (i *EvenNumberIterator) Value() int
例子code
package main import ( "fmt" "log" ) // To run: // go run next.go // EvenNumberIterator generates even number type EvenNumberIterator struct { max int currValue int err error } // NewEvenNumberIterator creates new number iterator func NewEvenNumberIterator(max int) *EvenNumberIterator { var err error if max < 0 { err = fmt.Errorf("'max' is %d, should be >= 0", max) } return &EvenNumberIterator{ max: max, currValue: 0, err: err, } } // Next advances to next even number. Returns false on end of iteration. func (i *EvenNumberIterator) Next() bool { if i.err != nil { return false } i.currValue += 2 return i.currValue <= i.max } // Value returns current even number func (i *EvenNumberIterator) Value() int { if i.err != nil || i.currValue > i.max { panic("Value is not valid after iterator finished") } return i.currValue } // Err returns iteration error. func (i *EvenNumberIterator) Err() error { return i.err } func printEvenNumbers(max int) { iter := NewEvenNumberIterator(max) for iter.Next() { fmt.Printf("n: %d\n", iter.Value()) } if iter.Err() != nil { log.Fatalf("error: %s\n", iter.Err()) } } func main() { fmt.Printf("Even numbers up to 8:\n") printEvenNumbers(8) fmt.Printf("Even numbers up to 9:\n") printEvenNumbers(9) fmt.Printf("Error: even numbers up to -1:\n") printEvenNumbers(-1) }
// 定義一個返回channel的函數 func generateEvenNumbers(max int) chan IntWithError // IntWithError struct type IntWithError struct { Int int Err error } // 調用方法,range方法能夠接chan遍歷的特性 func printEvenNumbers(max int) { for val := range generateEvenNumbers(max) { if val.Err != nil { log.Fatalf("Error: %s\n", val.Err) } fmt.Printf("%d\n", val.Int) } } // 完整generateEvenNumbers func generateEvenNumbers(max int) chan IntWithError { ch := make(chan IntWithError) go func() { defer close(ch) if max < 0 { ch <- IntWithError{ Err: fmt.Errorf("'max' is %d and should be >= 0", max), } return } for i := 2; i <= max; i += 2 { ch <- IntWithError{ Int: i, } } }() return ch }
例子:htm
package main import ( "fmt" "log" ) // To run: // go run channel.go // IntWithError combines an integer value and an error type IntWithError struct { Int int Err error } func generateEvenNumbers(max int) chan IntWithError { ch := make(chan IntWithError) go func() { defer close(ch) if max < 0 { ch <- IntWithError{ Err: fmt.Errorf("'max' is %d and should be >= 0", max), } return } for i := 2; i <= max; i += 2 { ch <- IntWithError{ Int: i, } } }() return ch } func printEvenNumbers(max int) { for val := range generateEvenNumbers(max) { if val.Err != nil { log.Fatalf("Error: %s\n", val.Err) } fmt.Printf("%d\n", val.Int) } } func main() { fmt.Printf("Even numbers up to 8:\n") printEvenNumbers(8) fmt.Printf("Even numbers up to 9:\n") printEvenNumbers(9) fmt.Printf("Error: even numbers up to -1:\n") printEvenNumbers(-1) }
經過context實現cancel中止迭代功能blog
package main import ( "context" "fmt" "log" ) // To run: // go run channel-cancellable.go // IntWithError combines an integer value and an error type IntWithError struct { Int int Err error } func generateEvenNumbers(ctx context.Context, max int) chan IntWithError { ch := make(chan IntWithError) go func() { defer close(ch) if max < 0 { ch <- IntWithError{ Err: fmt.Errorf("'max' is %d and should be >= 0", max), } return } for i := 2; i <= max; i += 2 { if ctx != nil { // if context was cancelled, we stop early select { case <-ctx.Done(): return default: } } ch <- IntWithError{ Int: i, } } }() return ch } func printEvenNumbersCancellable(max int, stopAt int) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ch := generateEvenNumbers(ctx, max) for val := range ch { if val.Err != nil { log.Fatalf("Error: %s\n", val.Err) } if val.Int > stopAt { cancel() // notice we keep going in order to drain the channel continue } // process the value fmt.Printf("%d\n", val.Int) } } func main() { fmt.Printf("Even numbers up to 20, cancel at 8:\n") printEvenNumbersCancellable(20, 8) }