broadcast.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. package pathway
  2. import (
  3. "io"
  4. )
  5. type broadcastWriter struct {
  6. writers []io.Writer
  7. }
  8. func (t *broadcastWriter) Close() (err error) {
  9. for i := 0; i < len(t.writers); i++ {
  10. if w, ok := t.writers[i].(io.WriteCloser); ok {
  11. if e := w.Close(); e != nil {
  12. err = e
  13. }
  14. }
  15. }
  16. return
  17. }
  18. func (t *broadcastWriter) Write(p []byte) (n int, err error) {
  19. for i := 0; i < len(t.writers); i++ {
  20. n, err = t.writers[i].Write(p)
  21. if err == nil && n != len(p) {
  22. err = io.ErrShortWrite
  23. }
  24. if err != nil {
  25. // if not at the end, move last to here and redo this
  26. if i < len(t.writers)-1 {
  27. // close the writer if it implements WriteCloser
  28. if w, ok := t.writers[i].(io.WriteCloser); ok {
  29. defer w.Close()
  30. }
  31. t.writers[i] = t.writers[len(t.writers)-1]
  32. i = i - 1
  33. }
  34. // always shorten list by one to drop the last one
  35. t.writers = t.writers[:len(t.writers)-1]
  36. }
  37. }
  38. if len(t.writers) <= 0 {
  39. return 0, err
  40. }
  41. return len(p), nil
  42. }
  43. // BroadcastWriter creates a writer that duplicates its writes to all the
  44. // provided writers, similar to the Unix tee(1) command.
  45. //
  46. // Each write is written to each listed writer, one at a time.
  47. // If a listed writer returns an error, that overall write operation
  48. // continues and the offending writer is dropped from the list.
  49. //
  50. // Only if all writers are dropped, the last error is returned at the end.
  51. func BroadcastWriter(writers ...io.Writer) io.WriteCloser {
  52. allWriters := make([]io.Writer, 0, len(writers))
  53. for _, w := range writers {
  54. if bw, ok := w.(*broadcastWriter); ok {
  55. allWriters = append(allWriters, bw.writers...)
  56. } else {
  57. allWriters = append(allWriters, w)
  58. }
  59. }
  60. return &broadcastWriter{allWriters}
  61. }