Serializing/Deserializing a complex GO struct to store externally (i.e. in a database, redis, or text file)
- Posted by Michael MacDonald
- on May, 19, 2018
- in Go
- Blog No Comments.
Sometimes one needs to serialize data to store outside of a go application. One common approach is to save it as a JSON blob which can have it’s own challenges when retrieving it. In this article I will show you how to make use of GOB to serialize a complex struct into textual data than can be stored in any data store and then returned to its original structure when decoded.
package main import ( "bytes" "context" "encoding/base64" "encoding/gob" "log" "googlemaps.github.io/maps" "github.com/davecgh/go-spew/spew" ) func main() { sourceStruct := getMap() spew.Dump(sourceStruct) // Show the original structure to be encoded valueToEncode := encodeToGob(&sourceStruct) encodedBase64Value := base64encode(valueToEncode) spew.Dump(encodedBase64Value) // Show the encoded value /* Now that everything has been encoded we can decode it and we should get back the sane struct that we encoded */ /* We need to make the gob package aware of what types we've encoded so that we can decode it. */ gob.Register([]maps.GeocodingResult{}) var decodedStruct []maps.GeocodingResult decodedValue := base64decode(encodedBase64Value) decodeFromGob(decodedValue, &decodedStruct) spew.Dump(decodedStruct) // Show the decoded structure, which should be the same as the original /* Success */ } func getMap() []maps.GeocodingResult { APIKey := "[Google API KEY]" c, _ := maps.NewClient( maps.WithAPIKey(APIKey), ) r := &maps.GeocodingRequest{ Address: "1600 Pennsylvania Ave NW", Region: "us", } response, err := c.Geocode(context.Background(), r) if err != nil { log.Fatal(err) } return response } func encodeToGob(source interface{}) []byte { var buff bytes.Buffer encoder := gob.NewEncoder(&buff) err := encoder.Encode(source) if err != nil { log.Fatal(err) } return buff.Bytes() } func decodeFromGob(source []byte, destination interface{}) { decoder := gob.NewDecoder(bytes.NewBuffer(source)) err := decoder.Decode(destination) if err != nil { log.Fatal(err) } } func base64encode(source []byte) []byte { encodedBytes := make([]byte, base64.URLEncoding.EncodedLen(len(source))) base64.URLEncoding.Encode(encodedBytes, source) return encodedBytes } func base64decode(source []byte) []byte { decodedBytes := make([]byte, base64.URLEncoding.DecodedLen(len(source))) _, err := base64.URLEncoding.Decode(decodedBytes, source) if err != nil { log.Fatal(err) } return decodedBytes }
Related
Comments & Responses
Recent Posts
- The shape of structured data
- Writing very small executable
- The challenge of type asserting []interface{} to string slices.
- Serializing/Deserializing a complex GO struct to store externally (i.e. in a database, redis, or text file)
- Fun with golang, Google Maps api, and proxying requests