Need to modify type of field for protobuf - protocol-buffers

I have quick question for modifying type of field for protobuf.
I have create the int64 id something like below.
message test {
int64 id = 1;
}
And I find out I can not set this id as null because of the type.
Therefore, I would like to modify it from int64 to int64value but do not sure is there any standard way for this kind of operation.
message test {
// int64 id = 1;
int64value id = 2;
}
or
message test {
int64 id = 1 [deprecated=true];
int64value id = 2;
}
Thanks and open to any kind of input!
I would like to get more standard way for this kind of operation.

You can reference values by field number or by name. So your first approach works. As long as you do not need backwards compatibility you could just change the id from int to your id type. This would result in a cleaner code.
For the use of the deprecated Attribut you could check out this:
Google protobuf 3: deprecated a field, but cannot remove the dependencies?

Related

update a map whose value is an array of object but get error

I just started learning Golang today. So, I suppose this question is a basic one howerver I tried what I can try, but get error.
So, I have defined a Student struct type:
type Student struct {
firstname string `json:"first_name"`
id int `json:"id"`
}
I want to have a map data structure, in which the map's key represent "class id" & the value of each key in this map is an array of Student. This is what I have tried:
var studentsMap = make(map[int][]Student)
func registerStudent(classId int, studentName string, studentId int) {
var studentsInClass = studentsMap[classId]
if studentsInClass == nil {
studentsInClass = []Student{}
}
// append the new student to the studentsInClass array
var updatedStudentsArr = append(studentsInClass, Student{studentName, studentId})
// update the map for this class id with updated array of students
// Compiler ERROR: Cannot use 'updatedStudentsArr' (type []Student) as the type Student
studentsMap[classId] = updatedStudentsArr
}
As you see in my comment in the code, when I try to update the studentsMap with the new array, I get compiler error Cannot use 'updatedStudentsArr' (type []Student) as the type Student. Why is that? My guess is that I defined wrongly the studentsMap map type, but how to fix?
The code you posted seems to be working fine, as pointed out by #nipuna in the comments.
As a small note, when you test for a key,value existence in go you get two values, the latter being a boolean. You can thus use the following to test whether studentsMap[classId] exists
studentsInClass, ok := studentsMap[classId]
if !ok {
studentsInClass = []Student{}
}
Regarding your second question related to #Volker's comment, you can read more about exporting struct fields in the following answers.
If you are using an IDE, it might be warning you about it (e.g. in VSCode I get struct field firstname has json tag but is not exported).
https://stackoverflow.com/a/50320595/5621318
https://stackoverflow.com/a/11129474/5621318
https://stackoverflow.com/a/25595269/5621318

Replace field with same type, but different meaning in Protocol Buffers

I'd like to update a message in Protocol Buffers:
message Person {
string name = 1;
}
Now, suppose that I don't want a name for a Person, but only its address:
message Person {
string address = 1;
}
Now, the id could remain 1 since the type is always a string, but I was wondering if it's better to rewrite the message in this way:
message Person {
string address = 2;
reserved 1;
}
in order to have more readability between versions.
you can just change the field name safely(if you want to keep same id and same type), please check below post would help you.
Protocol buffer: does changing field name break the message?
and also in my opion it is always good have
required or optional
annotation to the message fields

Sqlx "missing destination name" for struct tag through pointer

I have a model like this:
type Course struct {
Name string `db:"course_name"`
}
type Group struct {
Course *Course
}
type Groups []Group
And when i try to do sqlx.Select for Groups with a query like this:
SELECT c.name as course_name FROM courses as c;
I get
missing destination name course_name in *main.Groups
error.
What is the issue with this code?
You need to use sqlx.Select when you are selecting multiple rows and you want to scan the result into a slice, as is the case for your query, otherwise use sqlx.Get for a single row.
In addition, you can't scan directly into a Group struct because none of its fields are tagged (unlike the Course struct), and the Course field isn't embedded.
Try:
course := Course{}
courses := []Course{}
db.Get(&course, "SELECT name AS course_name FROM courses LIMIT 1")
db.Select(&courses, "SELECT name AS course_name FROM courses")
I changed Course *Course to Course Course - no effect.
When i made it embedded like this:
type Group struct {
Course
}
it worked.
This is also valid:
type Group struct {
*Course
}
Looks like sqlx doesn't understand anything except embedded fields.
Ok, so when you are using an embbeded struct with Sqlx, capitalization is important, at least in my case.
You need to refer to the embedded struct in your sql, like so:
select name as "course.name" from courses...
Notice that course is lower case and the naming involves a dot/period between table and column.
Then your Get or Select should work just fine.

Gocql custom marshaller

I have a table with a tuple column that is made up of an int64 paired with a uuid:
CREATE TABLE ks.mytable {
fileid frozen <tuple <bigint, uuid>>,
hits counter,
...
and I can currently set the field using a cql statement like:
UPDATE ks.mytable hits = hits + 1 WHERE fileid=(? ?);
and I pass in 2 variables as arguments, an int64 and a gocql.UUID.
Instead of moving 2 variables around everywhere, I want to put these in a struct, something like
type MyID struct {
id int64
uid gocql.UUID
}
then use a Marshaller to pass these into the UPDATE statement.
Is this possible? I am not sure if I can pass in a single variable for the tuple field. If so, how can I do this? I can't figure out how - I was trying to mimic https://github.com/gocql/gocql/blob/master/marshal_test.go#L935 but I'm getting errors where I can't set the fields in the struct (cannot refer to unexported field or method proto)
As you mentioned, you are getting the following error:
cannot refer to unexported field or method proto
This means you need to export your fields inside the struct and that means beginning with a capital letter in Go. So your struct should be:
type MyID struct {
Id int64
Uid gocql.UUID
}
Then, it should work.

xpath like query for protobuf messages

I am looking for a xpath like query language for protobuf messages. For example, for the Person message shown below [ borrowed from the Developer guide ]
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
I would like to have methods like
XPBQuery.get(person, "$.id") ==> returns the id
XPBQuery.get(person, "$.name") ==> returns the name
XPBQuery.get(person, "$.phone.number[0]") ==> returns the first phone number
One way is to convert the proto to Json and use a JsonPath/JsPath API's. But it may be expensive to convert to Json everytime especially for large Proto objects.
Any help is much appreciated.
Thanks,
Irfan
Support for that is coming in protobuf v3: https://github.com/google/protobuf/blob/4644f99d1af4250dec95339be6a13e149787ab33/src/google/protobuf/field_mask.proto
While looking for a solution to a similar problem I discovered:
PbQuery (python)
protobuf-utils (java)
protobuf-el (java)
(I did not use those libraries as my target language is C++, but hope this might help someone else)
Good luck!

Resources