Yan4321
Yan4321

Reputation: 339

go: Add writers to io.writer using multiWriter

I'm new to Go. I have a map which indicates which writers are active:

var writers map[int]bool

I want to iterate over the map, and create a writer which represents all active writers using multiWriter()

I am using the following code snippet:

func setupMultiLoggers() {
var mw io.Writer
for k, v := range writers {
    if v != true {
        continue
    }
    switch k {
    case 0:
        if mw == nil {
            mw = writer0
        } else {
            mw = io.MultiWriter(mw, writer0)
        }
    case 1:
        if mw == nil {
            mw = os.Stdout
        } else {
            mw = io.MultiWriter(mw, os.Stdout)
        }
    case 2:
        if mw == nil {
            mw = writer2
        } else {
            io.MultiWriter(mw, writer2)
        }
    default:
    }
}
log.SetOutput(mw)

}

When initializing the all 3 values of the map to true and then testing writer2, it sometimes works and sometimes doesn't (code in case 2 always executes)

If I just use

log.SetOutput(io.MultiWriter(writer0, os.Stdout, writer2))

It always works as expected.

I cannot seem to understand why my original code doesn't reliably work. I have a feeling there is a more clean way to "concatenate" writers

EDIT: I've found my (stupid) bug. assignment to mw was missing in the third case. Still looking for a more clean way to "concatenate" writers.

Upvotes: 0

Views: 1117

Answers (2)

peterSO
peterSO

Reputation: 166569

For example,

var writers map[int]bool

var writer0, writer2 io.Writer

func setupMultiLoggers() {
    var mw []io.Writer
    for k, v := range writers {
        if v == false {
            continue
        }
        switch k {
        case 0:
            mw = append(mw, writer0)
        case 1:
            mw = append(mw, os.Stdout)
        case 2:
            mw = append(mw, writer2)
        }
    }
    log.SetOutput(io.MultiWriter(mw...))
}

Upvotes: 1

driusan
driusan

Reputation: 550

You don't seem to have a map of writers, you have a map of ints to bools. Presumably, the ints represent the file descriptor.

The easiest way to do it would probably to change it from map[int]bool to map[io.Writer]bool, then you can iterate through them and add them to a slice with append.

ws := make([]io.Writer, 0)
for k, v : = range(writers) {
    if v != true {
        continue
    }
    ws = append(ws, k)
}

After that, you can just create a multiwriter directly by giving the slice to your MultiWriter call.

w := io.MultiWriter(ws...)
log.SetOutput(w)

(The ... in a function parameter after a slice means to expand the slice into arguments to the function call)

You can do the same thing while keeping it map[int]bool, but you'll need a switch similar to what you already have to convert your int into an io.Writer

Upvotes: 3

Related Questions