Source File
netchan.go
Belonging Package
go.pact.im/x/netchan
// Package netchan provides an in-memory implementation of the [net.Listener]// interface, allowing programs to simulate network connections using channels// and pipes instead of real network sockets.package netchanimport ()var _ net.Listener = (*Listener)(nil)// ErrClosed indicates that the [Listener] has been closed and no further// operations can be performed.var ErrClosed = errors.New("netchan: closed")// chanAddr implements the [net.chanAddr] interface representing the network// address of an in-memory [Listener]. Since connections are in-memory, chanAddr// returns constant values indicating the connection uses channels.type chanAddr struct{}// Network returns the name of the network, which is always "chan".func (chanAddr) () string { return "chan" }// String returns a string representation of the Addr, which is always "chan".func (chanAddr) () string { return "chan" }// Listener implements the [net.Listener] interface using channels for// accepting connections. Incoming connections are sent on an internal// channel and accepted by Accept calls. The Listener can be closed to// unblock Accept calls and signal shutdown.type Listener struct {addr net.Addrconn chan net.Conndone chan struct{}once sync.Once}// NewListener returns a new Listener with the default address.func () *Listener {return NewListenerAddr(chanAddr{})}// NewListenerAddr returns a new Listener instance with the specified network// address.func ( net.Addr) *Listener {return &Listener{addr: ,conn: make(chan net.Conn),done: make(chan struct{}),}}// Accept waits for and returns the next connection sent to the listener’s// connection channel. If the listener is closed, Accept returns [ErrClosed].func ( *Listener) () (net.Conn, error) {select {// Accept should return an error after Close.case <-.done:return nil, ErrCloseddefault:}:select {case , := <-.conn:// Handle unlikely case of close(l.C()).if ! {return nil, ErrClosed}// Allow sending nil connection to wait for Accept call.if == nil {goto}return , nil// Unblock Accept when Close is called.case <-.done:return nil, ErrClosed}}// Addr implements the [net.Listener] interface.func ( *Listener) () net.Addr {return chanAddr{}}// Close closes the listener and unblocks all Accept calls.func ( *Listener) () error {.once.Do(func() { close(.done) })return nil}// C returns the internal channel used to send [net.Conn] connections to the// Accept callers. The returned channel should not be closed; use Close method// to unblock Accept instead.//// Sending a nil connection on this channel is allowed and can be used// to wait for the Accept caller to be ready.func ( *Listener) () chan net.Conn {return .conn}// Done returns a channel that is closed when the Listener is closed.func ( *Listener) () <-chan struct{} {return .done}// Dial creates a new in-memory connection pair using net.Pipe and sends the// server side connection to the Listener’s internal connection channel.//// It returns the client side connection, which can be used to communicate// with the accepted connection on the Listener side.//// Dial blocks until the server side connection is accepted by a call to Accept,// or until the Listener is closed or the provided context is canceled.func ( *Listener) ( context.Context) (net.Conn, error) {, := net.Pipe()select {case .conn <- :return , nilcase <-.done:return nil, ErrClosedcase <-.Done():return nil, .Err()}}
The pages are generated with Golds v0.7.6. (GOOS=linux GOARCH=amd64)