The app I’m working on is passing structs back and forward over a web connection using JSON encoding.
There are multiple request and response structs and I want to write a generic Marshal function that will take any of them, marshal it and then return the string.
I’m going to get the terminology wrong here, but in this example, I created a base struct with a Marshal function and Request1 included(?) it. Running the Marshal function doesn’t return any data. I know that this is because none of the attributes in Request1 are in the base so they aren’t seen when the function runs. I’m happy with why this isn’t working.
Request2 has its own Marshal function which works fine.
Is there a way to do some type of inheritance so that I can have a single Marshal function and not have to repeat the same code for every request and response struct?
I’ve just read a couple of articles on annotations but can’t understand how they would help here. Do you know any examples of using them in the way I would need to?
Yeah, you are right, I missunderstood your issue and only realize now (after I had some sleep and coffee in exactly this order) that its not about marshalling itself, but about having an easy way to marshall into a string.
That will attempt to encode and return the indented JSON of input. It’ll return []byte if you want that to be a string, you can either cast the resulting value or update the above to the following:
That is exactly what I wanted, thanks. I’m going to use the full version but I’ve simplified it to try to work out what is going on.
Am I right in thinking that as long as whatever is passed in can be marshalled that anything can be passed? And the interface is a generic type that allows this?
Well, my version does return a string directly, not []byte, dunno which one is it you like. Also my version is a bit more typesafe than just using interface{}. At the end you have to shoose on your own which suites better in your project.
In that version, you’ve removed type safety (the foo method) as the JSONMessageMarker doesn’t implement any methods anymore, meaning you’ll get a similar result to using interface{} in any event.
For example, the following will execute without issue in your version:
However, in the version @NobbZ originally posted, you will get an error, because type []string doesn’t implement the foo method, as you would expect. To get type safety you need to ensure the JSONMessageMarker interface actually implements something.
That explains the foo(), thanks. I thought that was just a demonstration that I could put functions I wanted shared on the JSONMessage struct.
I think type safety doesn’t matter too much in this instance as I’m fairly sure anything I might pass in would be able to be marshalled, but I will probably stick with the @NobbZ version to save me messing up and trying to pass something I shouldn’t.
That’s a good idea, bare in mind, you’ll need to make sure anything that you wish to Marshal using MarshallJSONMessage will need to implement foo and any other associated interface methods.
Looking into the Go native library is super useful as well when it comes to interfaces, look particularly at the Reader and Writer interfaces, they’re used repeatedly and are extremely simple interfaces (each with one method Read and Write respectively if I remember correctly).
Maybe you could either consider a total generic that relieves you from any marshalling concern (as far as possible). Have you heard about gRpc ? It’s really fast and can use Json as message format : https://grpc.io/blog/grpc-with-json
Someone has already done the job of creating the json codec for Go, here it is with example : https://jbrandhorst.com/post/grpc-json/
Have a nice day.