Golang gRPC database serialization key format defined on struct - go

I want to use the go structs that are generated by the gRPC compiler directly for database transactions but the problem is that only the json serialization field is set by gRPC.
Is there a way to either set additional serialization keys (like shown below) or is there another golang specific way to tell the database driver (sqlx on top of database/sql) that the json key format should be used?
Some example - The gRPC compiler creates the following struct:
type HelloWorld struct {
TraceId string `protobuf:"bytes,1,opt,name=trace_id,json=traceId,proto3" json:"trace_id,omitempty"`
...
What I would like to have:
type HelloWorld struct {
TraceId string `db:"trace_id" protobuf:"bytes,1,opt,name=trace_id,json=traceId,proto3" json:"trace_id,omitempty"`
...
A temporary workaround would be to write sql queries that use aliases (traceid instead of trace_id in this example) but it doesn't feel consistent and adds a lot of complexity.

I think that currently there is no built-in way of doing this. However, you might be interested in following this thread: https://github.com/golang/protobuf/issues/52
Other than that I think you can just create yet another struct for database access and make the mapping explicit which might be more readable.

Related

Gorm relationship and issues

I was creating my first-ever rest API in golang with fiber and form. I wanted to create a model that had a slice of strings, but gorm does not allow me to do so. SO, the next thing I tried was to use a map, hoping that it will be easily converted to JSON and saved to my postgres instance. But the same, gorm does not support maps. So, I created another struct into which I put all the data in a not-so-elegant way, where I made a single string value for each possible string I can save, and then I embedded this struct into the other. But now the compiler's complaints that I have to save a primary key into it, and not raw json given from the request. I am a bit overwhelmed by now
If someone knows I way that I can use to save all the data I need into the way that respects my requirements (slice of string, easy to parse when I read from the database), and to finish this CRUD app, I would really be thankful for that. thank you a lot

How to unmarshal protbuf data into custom struct in Golang

I have a proxy service that translate protobuf into another struct. I
can just write some manual code to do that, but that is inefficient and boilerplate. I can also transform the protobuf data to JSON, and deserlize the JSON data into the destination struct, but the speed is slow and it is CPU heavy.
The Unmarshaler interface is now deprecated, and Message interface have internal types which I cannot implement in my project.
Is there a way I can do this now?
Psuedo code: basically, if Go's reflection supports setting and getting of struct / class fields by some sort of field identifier, then you can do this. Something like this in C# works, so long as the field types in the two classes are the same (because in C#, I'm doing object = object, which ends up being OK if they're the same actual type).
SourceStructType sourceStruct;
DestStructType destStruct;
foreach (Field sourceField in sourceStruct.GetType().GetFields())
{
Field destField = destStruct.GetType().FindFieldByName(sourceField.name);
destStruct.SetFieldValue(destField) = sourceStruct.GetFieldValue(sourceField);
}
If the structs are more complex - i.e. they have structs within them, then you'll have to recurse down into them. It can get fiddly, but once written you'll never have to write it ever again!

Why are unexported struct fields purposely not marshalled in the json package

In the json package if you want to utilize tags to marshall and unmarshall structs the field must be exported. I always thought this was a limitation on the reflect package but it seems to be explicitly rejected here.
I would like to know what I am missing or the design choices behind this as it creates one of the following issues normally.
Exporting more fields than I want allowing users to change values without using potential getters and setters.
A lot of extra code if you chose to solve the above problem by making a second identical struct just for tag usage and make it unexported.
Here is a playground of code being able to read unexported tags.
Edit: Better playground thanks to #mkopriva

Handling configurations without defining explicit type objects

I am following the solution (accepted answer) given here as to load configuration values in Go.
So far so good.
However, I want to use standard configuration load functions across different modules of the application and for simplicity and ease of it I am trying to achieve loading configurations without explicitly defining a customer object such as type Configuration struct.
Because each configuration file would be different and I don't want to define multiple structs and structs everywhere and then change them when a new value is added/deleted in the configurations.
I might be unfair to compare but I am looking for which in python would be just like this:
//in config.py
ENVIRONMENT = 'PROD'
//in main.py
import config
...
if config.ENVIRONMENT == 'PROD':
...
Is there such a possibility?
You can use a map[string]string type if all your config values are strings or a map[string]interface{} type if you need arbitrary value types.
Although map[string]interface{} is a bit more cumbersome and a bit less safe, because you can cast interface{} to any type.
Here is a guide for using map[string]interface{}: https://bitfieldconsulting.com/golang/map-string-interface

Stateful implementation of yaml.v2 Unmarshaller interface?

This could either be a file path question, or a question on how to best implement an interface.
Given the following very simple yaml:
name: MyYamlName
data: some/relative/path.txt
I would like to unmarshal it to the following struct:
type VerySimple struct {
name string
data io.Reader
}
I'm already using the yaml.v2 library, and know that for simple types, I can implement the Unmarshaller interface. However, in my program, I can't assume an absolute root from which to base the relative path in the data field.
Is there a way to implement the Unmarshaller interface to pass a working directory, or maybe a different way to handle relative paths in Go?
It's pretty clear from the API documentation that this isn't supported. The natural way to support it, IMO, would be with a Decoder type, analogous to the json.Decoder type. It could be initialized with a root include path, or a list of include paths to search.
There is already a request for such a feature. It does mention working with multiple documents, which probably implies including an include path, although that specific feature has not yet been explicitly mentioned. I suggest offering your ideas in that thread.

Resources