Last active
April 19, 2022 14:08
-
-
Save Mattie112/3118743a33086f3329121f9b2721e66a to your computer and use it in GitHub Desktop.
Munisense Golang Workshop
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"math/rand" | |
"time" | |
) | |
const n = 20 | |
func main() { | |
startTime := time.Now().UnixMilli() | |
fmt.Print("Filling input channel.... ") | |
inputCh := make(chan InputItem, n) | |
generateInput(n, inputCh) | |
close(inputCh) | |
fmt.Println("DONE!") | |
outputCh := make(chan OutputItem, 1000) | |
dataMap := map[time.Time][]uint64{} | |
// First we group the inputs per day in a map | |
for input := range inputCh { | |
// Calculate the start of day | |
startOfDayTimestamp := startOfDay(input.Timestamp) | |
// Make sure the dataMap has an entry for each startOfDay | |
if _, exists := dataMap[startOfDayTimestamp]; !exists { | |
dataMap[startOfDayTimestamp] = make([]uint64, 0) | |
} | |
dataMap[startOfDayTimestamp] = append(dataMap[startOfDayTimestamp], input.Value) | |
} | |
for day, elems := range dataMap { | |
min, max, avg := calculate(elems) | |
outputCh <- OutputItem{ | |
Timestamp: day, | |
DayMax: max, | |
DayMin: min, | |
DayAvg: avg, | |
} | |
} | |
close(outputCh) | |
// Listens on the output channel and prints the results | |
for item := range outputCh { | |
fmt.Printf("Day: %s, Avg: %0.2f, Min: %d, Max: %d\n", item.Timestamp, item.DayAvg, item.DayMin, item.DayMax) | |
} | |
fmt.Printf("Done in %d milliseconds!", time.Now().UnixMilli()-startTime) | |
} | |
type InputItem struct { | |
Timestamp time.Time | |
Value uint64 | |
} | |
type OutputItem struct { | |
Timestamp time.Time | |
DayMax uint64 | |
DayMin uint64 | |
DayAvg float32 | |
} | |
func calculate(elems []uint64) (min, max uint64, avg float32) { | |
// Fake expensive operation like connecting to a database | |
time.Sleep(100 * time.Millisecond) | |
total := uint64(0) | |
min = 18446744073709551615 | |
max = 0 | |
for _, elem := range elems { | |
total += elem | |
if elem < min { | |
min = elem | |
} | |
if elem > max { | |
max = elem | |
} | |
} | |
avg = float32(total) / float32(len(elems)) | |
return | |
} | |
func generateInput(n int, inputCh chan<- InputItem) { | |
for i := 0; i < n; i++ { | |
rand.Seed(int64(i)) | |
minTimestamp := int64(1640991600) | |
maxTimestamp := int64(1648764000) | |
unix := time.Unix(rand.Int63n(maxTimestamp-minTimestamp+1)+minTimestamp, 0) | |
inputCh <- InputItem{ | |
Timestamp: unix, | |
Value: uint64(rand.Intn(1000)), | |
} | |
} | |
} | |
func startOfDay(input time.Time) time.Time { | |
return input.Truncate(time.Hour * 24) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment