Skip to content

Instantly share code, notes, and snippets.

@alexmullins
Last active March 17, 2024 07:26
Show Gist options
  • Save alexmullins/1c6cc6dc38a8e83ed2f6 to your computer and use it in GitHub Desktop.
Save alexmullins/1c6cc6dc38a8e83ed2f6 to your computer and use it in GitHub Desktop.
Concurrent io.MultiWriter Implementation
package main
import (
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/hex"
"fmt"
"io"
"strings"
)
func main() {
input := "hello world"
fmt.Println("Input:", input)
r := strings.NewReader(input)
hashes := CalculateBasicHashes(r)
fmt.Println("Md5:", hashes.Md5)
fmt.Println("Sha1:", hashes.Sha1)
fmt.Println("Sha256:", hashes.Sha256)
fmt.Println("Sha512:", hashes.Sha512)
}
type HashInfo struct {
Md5 string
Sha1 string
Sha256 string
Sha512 string
}
func CalculateBasicHashes(rd io.Reader) HashInfo {
md5 := md5.New()
sha1 := sha1.New()
sha256 := sha256.New()
sha512 := sha512.New()
multiWriter := MultiCWriter(md5, sha1, sha256, sha512)
_, err := io.Copy(multiWriter, rd)
if err != nil {
fmt.Println(err.Error())
}
var info HashInfo
info.Md5 = hex.EncodeToString(md5.Sum(nil))
info.Sha1 = hex.EncodeToString(sha1.Sum(nil))
info.Sha256 = hex.EncodeToString(sha256.Sum(nil))
info.Sha512 = hex.EncodeToString(sha512.Sum(nil))
return info
}
type multiCWriter struct {
writers []io.Writer
}
func (t *multiCWriter) Write(p []byte) (n int, err error) {
type data struct {
n int
err error
}
results := make(chan data)
for _, w := range t.writers {
go func(wr io.Writer, p []byte, ch chan data) {
n, err = wr.Write(p)
if err != nil {
ch <- data{n, err}
return
}
if n != len(p) {
ch <- data{n, io.ErrShortWrite}
return
}
ch <- data{n, nil} //completed ok
}(w, p, results)
}
for range t.writers {
d := <-results
if d.err != nil {
return d.n, d.err
}
}
return len(p), nil
}
// MultiWriter creates a writer that duplicates its writes to all the
// provided writers, similar to the Unix tee(1) command.
func MultiCWriter(writers ...io.Writer) io.Writer {
w := make([]io.Writer, len(writers))
copy(w, writers)
return &multiCWriter{w}
}
@ibnishak
Copy link

NoobQn. Is this benchmarked? This article goes in detail as to why concurrency in such a situation would actually be detrimental.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment