go select3 源码

  • 2022-07-15
  • 浏览 (909)

golang select3 代码

文件路径:/test/chan/select3.go

// run

// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Test the semantics of the select statement
// for basic empty/non-empty cases.

package main

import "time"

const always = "function did not"
const never = "function did"

func unreachable() {
	panic("control flow shouldn't reach here")
}

// Calls f and verifies that f always/never panics depending on signal.
func testPanic(signal string, f func()) {
	defer func() {
		s := never
		if recover() != nil {
			s = always // f panicked
		}
		if s != signal {
			panic(signal + " panic")
		}
	}()
	f()
}

// Calls f and empirically verifies that f always/never blocks depending on signal.
func testBlock(signal string, f func()) {
	c := make(chan string)
	go func() {
		f()
		c <- never // f didn't block
	}()
	go func() {
		if signal == never {
			// Wait a long time to make sure that we don't miss our window by accident on a slow machine.
			time.Sleep(10 * time.Second)
		} else {
			// Wait as short a time as we can without false negatives.
			// 10ms should be long enough to catch most failures.
			time.Sleep(10 * time.Millisecond)
		}
		c <- always // f blocked always
	}()
	if <-c != signal {
		panic(signal + " block")
	}
}

func main() {
	const async = 1 // asynchronous channels
	var nilch chan int
	closedch := make(chan int)
	close(closedch)

	// sending/receiving from a nil channel blocks
	testBlock(always, func() {
		nilch <- 7
	})
	testBlock(always, func() {
		<-nilch
	})

	// sending/receiving from a nil channel inside a select is never selected
	testPanic(never, func() {
		select {
		case nilch <- 7:
			unreachable()
		default:
		}
	})
	testPanic(never, func() {
		select {
		case <-nilch:
			unreachable()
		default:
		}
	})

	// sending to an async channel with free buffer space never blocks
	testBlock(never, func() {
		ch := make(chan int, async)
		ch <- 7
	})

	// receiving from a closed channel never blocks
	testBlock(never, func() {
		for i := 0; i < 10; i++ {
			if <-closedch != 0 {
				panic("expected zero value when reading from closed channel")
			}
			if x, ok := <-closedch; x != 0 || ok {
				println("closedch:", x, ok)
				panic("expected 0, false from closed channel")
			}
		}
	})

	// sending to a closed channel panics.
	testPanic(always, func() {
		closedch <- 7
	})

	// receiving from a non-ready channel always blocks
	testBlock(always, func() {
		ch := make(chan int)
		<-ch
	})

	// empty selects always block
	testBlock(always, func() {
		select {}
	})

	// selects with only nil channels always block
	testBlock(always, func() {
		select {
		case <-nilch:
			unreachable()
		}
	})
	testBlock(always, func() {
		select {
		case nilch <- 7:
			unreachable()
		}
	})
	testBlock(always, func() {
		select {
		case <-nilch:
			unreachable()
		case nilch <- 7:
			unreachable()
		}
	})

	// selects with non-ready non-nil channels always block
	testBlock(always, func() {
		ch := make(chan int)
		select {
		case <-ch:
			unreachable()
		}
	})

	// selects with default cases don't block
	testBlock(never, func() {
		select {
		default:
		}
	})
	testBlock(never, func() {
		select {
		case <-nilch:
			unreachable()
		default:
		}
	})
	testBlock(never, func() {
		select {
		case nilch <- 7:
			unreachable()
		default:
		}
	})

	// selects with ready channels don't block
	testBlock(never, func() {
		ch := make(chan int, async)
		select {
		case ch <- 7:
		default:
			unreachable()
		}
	})
	testBlock(never, func() {
		ch := make(chan int, async)
		ch <- 7
		select {
		case <-ch:
		default:
			unreachable()
		}
	})

	// selects with closed channels behave like ordinary operations
	testBlock(never, func() {
		select {
		case <-closedch:
		}
	})
	testBlock(never, func() {
		select {
		case x := (<-closedch):
			_ = x
		}
	})
	testBlock(never, func() {
		select {
		case x, ok := (<-closedch):
			_, _ = x, ok
		}
	})
	testPanic(always, func() {
		select {
		case closedch <- 7:
		}
	})

	// select should not get confused if it sees itself
	testBlock(always, func() {
		c := make(chan int)
		select {
		case c <- 1:
		case <-c:
		}
	})
}

相关信息

go 源码目录

相关文章

go doubleselect 源码

go fifo 源码

go goroutines 源码

go nonblock 源码

go perm 源码

go powser1 源码

go powser2 源码

go select 源码

go select2 源码

go select4 源码

0  赞