func(a *Address) Update(other Address, fm fieldmask.FieldMask) { iflen(fm) == 0 { // Clear the entire address. *a = other return }
if fm.Has("country") { a.Country = other.Country } if fm.Has("province") { a.Province = other.Province } if fm.Has("city") { a.City = other.City } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
func(p *Person) Update(other Person, fm fieldmask.FieldMask) { iflen(fm) == 0 { // Clear the entire person. *p = other return }
if fm.Has("name") { p.Name = other.Name } if fm.Has("age") { p.Age = other.Age } if addressFM, ok := fm.FieldMask("address"); ok { p.Address.Update(other.Address, addressFM) } }
It is fine to start with a monolithic architecture, but make sure to modularize it and architect it with the above three microservice principles (single purpose, loose coupling and high cohesion), except that the “services” are implemented in the same tech stack, deployed together and run in the same process.
Two mechanisms are supported for doing this: direct annotations in your .proto file, and in YAML as part of your gRPC API configuration file. We recommend using proto annotations for ease of reading and maintenance.
A slice is a descriptor of an array segment. It consists of a pointer to the array, the length of the segment, and its capacity (the maximum length of the segment).
So, we know that i is going to be allocated on the heap. But how does the runtime set that up? With the compiler’s help! We can get an idea from reading the generated assembly.