What's the difference between adding a channel vs doing subsequent calls for IO?

80 views
Skip to first unread message

minc....@gmail.com

unread,
Jan 20, 2022, 9:41:24 AM1/20/22
to golang-nuts
Hello,

I have a function to read from a connection and do some data processing and then write to another connection, the following are 2 different approaches. Here's the first approach without channel and go routines:

func (p *Proxy) pipe(from io.Reader, to io.Writer, dataHandler func(input []byte) ([]byte, error)) {
defer p.cancelGlobal()
for {

select {
case <-p.ProxyCtx.Done():
return
default:
}

buf := make([]byte, 4096)
n, err := from.Read(buf)
if err != nil {
return
}

var pktout []byte
if dataHandler != nil {
pktout, err = dataHandler(buf[0:n])
if err != nil {
p.log.Error("processing data error: ", err.Error(), ", ignoring...")
continue
}
} else {
pktout = buf[0:n]
}

if pktout != nil && len(pktout) > 0 {
if _, err = to.Write(pktout); err != nil {
p.log.Error(err.Error())
}
}
}
}

Here's the second approach which has a channel and a new Go routine:
func (p *Proxy) pipe(from io.Reader, to io.Writer, dataHandler func(input []byte) ([]byte, error)) {
defer p.cancelGlobal()
out := make(chan []byte)
go func() {
LOOP:
for {
select {
case <-p.ProxyCtx.Done():
break LOOP
case data := <-out:
var pktout []byte
var err error
if dataHandler != nil {
pktout, err = dataHandler(data)
if err != nil {
p.log.Error("processing data error: ", err.Error(), ", ignoring...")
continue
}
} else {
pktout = data
}

if pktout != nil && len(pktout) > 0 {
if _, err := to.Write(pktout); err != nil {
p.log.Error(err.Error())
}
}
}
}
}()
for {
select {
case <-p.ProxyCtx.Done():
return
default:
}

buf := make([]byte, 4096)
n, err := from.Read(buf)
if err != nil {
return
}
out <- buf[0:n]
}
}

What are the main differences between the 2 approches above and which one is better?  To me I think the first one is simpler. But what is the value of adding a channel in the 2nd approach?

Thanks,
Bin

Reply all
Reply to author
Forward
0 new messages