Created
April 27, 2022 18:13
-
-
Save arl/1ded641f0d7d739386a9f79e59d650d3 to your computer and use it in GitHub Desktop.
This file contains 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
module github.com/arl/gobtest | |
go 1.19 |
This file contains 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 ( | |
"bytes" | |
"encoding/gob" | |
"fmt" | |
"log" | |
"time" | |
) | |
type Message interface{} | |
func encodeMessage(enc *gob.Encoder, msg Message) error { | |
err := enc.Encode(&msg) | |
if err != nil { | |
return fmt.Errorf("failed encoding Message %+v: %v", msg, err) | |
} | |
return nil | |
} | |
func decodeMessage(dec *gob.Decoder) (Message, error) { | |
var msg Message | |
err := dec.Decode(&msg) | |
if err != nil { | |
return nil, fmt.Errorf("failed decoding Message: %v", err) | |
} | |
return msg, nil | |
} | |
func decodeConcrete[T Message](dec *gob.Decoder) (T, error) { | |
var msg Message | |
err := dec.Decode(&msg) | |
if err != nil { | |
t := new(T) | |
return *t, fmt.Errorf("failed decoding Message: %v", err) | |
} | |
return msg.(T), nil | |
} | |
type Measure struct { | |
Timestamp time.Time | |
Name string | |
Type string | |
DisplayName string | |
Unit string | |
Data string | |
} | |
func NewMeasure() Measure { | |
return Measure{ | |
Timestamp: time.Now(), | |
Name: "some name", | |
Type: "some type", | |
DisplayName: "some display name", | |
Unit: "some unit", | |
Data: "some data", | |
} | |
} | |
type Alert struct { | |
Timestamp time.Time | |
Name string | |
State string | |
Message string | |
} | |
func NewAlert() Alert { | |
return Alert{ | |
Timestamp: time.Now(), | |
Name: "some name", | |
State: "some state", | |
Message: "some message", | |
} | |
} | |
func concrete() { | |
gob.RegisterName("measurement", Measure{}) | |
gob.RegisterName("alert", Alert{}) | |
wire := bytes.Buffer{} | |
enc := gob.NewEncoder(&wire) | |
encodeMessage(enc, NewMeasure()) | |
encodeMessage(enc, NewAlert()) | |
dec := gob.NewDecoder(&wire) | |
myMeasure, err := decodeConcrete[Measure](dec) | |
if err != nil { | |
log.Fatal(err) | |
} | |
fmt.Printf("%+v\n", myMeasure) | |
myAlert, err := decodeConcrete[Alert](dec) | |
if err != nil { | |
log.Fatal(err) | |
} | |
fmt.Printf("%+v\n", myAlert) | |
} | |
func dynamic() { | |
gob.RegisterName("measurement", Measure{}) | |
gob.RegisterName("alert", Alert{}) | |
wire := bytes.Buffer{} | |
enc := gob.NewEncoder(&wire) | |
encodeMessage(enc, NewMeasure()) | |
encodeMessage(enc, NewAlert()) | |
dec := gob.NewDecoder(&wire) | |
msg1, err := decodeMessage(dec) | |
if err != nil { | |
log.Fatalf("error decoding msg1: %v", err) | |
} | |
msg2, err := decodeMessage(dec) | |
if err != nil { | |
log.Fatalf("error decoding msg2: %v", err) | |
} | |
doSomethingDynamic := func(imsg Message) { | |
switch msg := imsg.(type) { | |
case Measure: | |
fmt.Printf("%+v\n", msg) | |
case Alert: | |
fmt.Printf("%+v\n", msg) | |
default: | |
panic("") | |
} | |
} | |
doSomethingDynamic(msg1) | |
doSomethingDynamic(msg2) | |
} | |
func main() { | |
// When you already know the type of the concrete message you're receveing. | |
concrete() | |
// When you can receive multiple types, and switch based on the final type. | |
dynamic() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment