Package [github.com/kjk/common/siser](https://github.com/kjk/common/tree/main/siser)
provides simple serialization for Go.
The package consists of 2 layers:
- serialization of records (multiple key / value pairs) into a blob of bytes
- framing those bytes into self-delimited data packet with a timestamp and a type
Writing records to a file
A common use case is writing a sequence of records to a file.
Let’s say we want to log information about HTTP requests. A single record has information about a single HTTP request (like URL, HTTP response code etc.).
This information is represented as key / value pairs (both strings).
func createWriter() (*siser.Writer, error) {
f, err := os.Create("http_access.log")
if err != nil {
return nil, err
}
w := siser.NewWriter(f)
return w, nil
}
func logHTTPRequest(w *siser.Writer, url string, ipAddr string, statusCode int) error {
var rec siser.Record
// you can append multiple key/value pairs at once
rec.Append("url", url, "ipaddr", ipAddr)
// or assemble with multiple calls
rec.Append("code", strconv.Itoa(statusCode))
_, err := w.WriteRecord(&rec)
return err
}
The data will be written to writer underlying siser.Writer
as:
61 1553488435903 httplog
url: https://blog.kowalczyk.info
ipaddr: 10.0.0.1
code: 200
What it means:
61
is the size of the data. This allows us to read the exact number of bytes in the record
1553488435903
is a timestamp which is Unix epoch time in milliseconds (more precision than standard Unix time which is in seconds)
httplog
is optional name of the record. This allows us to easily write multiple types of records to the same file
To read back all records from the file:
f, err := os.Open("http_access.log")
fatalIfErr(err)
defer f.Close()
reader := siser.NewReader(f)
for reader.ReadNextRecord() {
rec := r.Record
name := rec.Name // "httplog"
timestamp := rec.Timestamp
code, ok := rec.Get("code")
// get rest of values and and do something with them
}
fatalIfErr(rec.Err())