Difference between initialization of struct slices - arrays

type Person struct {
ID int `json:"id"`
}
type PersonInfo []Person
type PersonInfo2 []struct {
ID int `json:"id"`
}
Is there have difference between PersonInfo (named slice of named structs) and PersonInfo2 (named slice of unnamed structs)

The main difference is how you have to initialize Person objects outside of the PersonInfo/PersonInfo2 initialization. Since PersonInfo2 is an array of the anonymous struct type we know nothing about this type outside of the PersonInfo2 initialization.
So they can both be initialized like this:
m := PersonInfo{{1}, {2}}
n := PersonInfo2{{1},{2}}
However if we want to append an element of the anonymous struct type we would have to specify the full type:
append(n, struct { ID int `json:"id"` }{3})
If we print these out we can see they appear to be the same:
fmt.Printf("%+v\n%+v", m, n)
Outputs:
[{ID:1} {ID:2}]
[{ID:1} {ID:2}]
However they wont be deeply equal because PersonInfo is an array of type Person and PersonInfo2 is an array of anonymous struct type. So the following:
if !reflect.DeepEqual(m,n) {
print("Not Equal")
}
will print "Not Equal".
Here is a link to see for yourself.
When appending to PersonInfo2 we have to repeat the anonymous struct type for every value we want to append, it is probably better to use PersonInfo as an array of type Person.

Go is using structural typing, that means, as long as the two types have the same underlying type, they are equivalent.
So, for your question: Person and struct{ ID int 'json:"id"'} is equivalent because they have the same underlying type, and therefore, PersonInfo and PersonInfo2 are also equivalent. I took of the json tags to simplify the example.
person1 := Person{1}
pStruct1 := struct{ID int}{2}
pInfo1 := PersonInfo{
person1,
pStruct1,
}
pInfo2 := PersonInfo2{
person1,
pStruct1,
}
fmt.Printf("%+v\n", pInfo1)
fmt.Printf("%+v", pInfo2);
//outputs
//PersonInfo: [{ID:1} {ID:2}]
//PersonInfo2: [{ID:1} {ID:2}]
Code example: https://play.golang.org/p/_wlm_Yfdy2

type PersonInfo is an object of Person, while PersonInfo2 is a class (or type in Golang) by itself. Even though their data structure is similar.
So, when you run DeepEqual() to check the similarity it will turn out to be false.
Example by previous comment:
if !reflect.DeepEqual(m,n) {
print("Not Equal")
}
Hope this helps.

Related

Can I use strings within an array to name struct variables using concatenation, macros, or similar?

I have an array of animal names in the order that I intend to create each struct 'animal' and store it in farm_animals, a struct of animals.
typedef struct ani animal;
animal* farm_animals[128] = {0};
Although the below code is totally invalid, I have included it here to show exactly what I have thought of achieving in practice. I want to declare a variable of type animal corresponding to a string literal in the array, and then somehow use that literal as the name of the animal and store it in an array.
char* animal_names [] = {"Oliver", "Marcus", "Mike", "John", "Tom", "Daisy", "Lilac", "Rose", "Jim"};
for (int i = 0; i < 9; i++) {
animal animal_names[i];
farm_animals[i] = animal_names[i];
}
I have researched and found many other similar posts which conclude that since C is a compiled not interpreted language, it is not possible to name a variable with the value of a string. However, I was wondering if it is possible to concatenate the string name with a suffix (like the index number) to create an entirely new 'string name' to refer to the animal. I have also though of a macro using an array or the same animal_names array, but this has not been clear for me to implement as a beginner.
I think this sort of idea in C is far-fetched, but I really wonder if there is a way to name these structs using a for loop and array of names, rather than manually creating 100+ structs.
Yes, it is not possible to dynamically name variables in C. If I understand correctly, you want to create an animal type corresponding to a string and then name it that name.
The advantage with using structs is that you can combine related/relevant data into a single variable (the struct) – which itself is a collection of multiple variables.
I would suggest organizing something like this:
typedef struct animal {
char[20] name;
char[20] type;
} animal;
You can replace the character array with a pointer to the string (char*) as well. Also, if you know the type of animals that could be created you can instead create an enum like this:
#define MAX_NAME_LEN 20
#define MAX_NUM_ANIMALS 10
enum animalType {
LION,
ELEPHANT,
FALCON,
PARROT
};
typedef struct animal {
char[MAX_NAME_LEN] name;
enum animalType type;
} animal;
int main(void) {
animal listOfAnimals[MAX_NUM_ANIMALS];
listOfAnimals[0].type = PARROT;
listOfAnimals[0].name = "my parrot";
return 0;
}
So, instead of making 100+ structs, you would make an array of structs and store the type of animal as a data member. Then you could use some mapping mechanism or conditional logic to assign these types to the struct variables as per your needs.

How do I Change the Position of Golang Struct Values?

How would I change the position of the json values?
What Im trying to achieve:
[{"key":"f","value":"f"},{"value":"f","key":"f"}]
Problem:
type Struct struct {
Key string `json:"key"`
Value string `json:"value"`
}
func main() {
test := []Struct{ {Key: "test",Value: "wep"}, {Value: "wep",Key: "test"}}
bytes, _ := json.Marshal(test)
fmt.Print(string(bytes))
}
Running this code prints [{"key":"test","value":"wep"},{"key":"test","value":"wep"}]
I have also tried doing something like this but it just printed empty values
type Struct struct {
Key string `json:"key"`
Value string `json:"value"`
Value2 string `json:"value"`
Key2 string `json:"key"`
}
But how would I be able to switch the position of the key and value field around?
type StructA struct {
Key string `json:"key"`
Value string `json:"value"`
}
type StructB struct {
Value string `json:"value"`
Key string `json:"key"`
}
func main() {
test := []interface{}{
StructA{Key: "test", Value: "wep"},
StructB{Value: "wep", Key: "test"},
}
bytes, _ := json.Marshal(test)
fmt.Print(string(bytes))
}
https://play.golang.org/p/72TWDU1BMaL
If you're using json.Marshal provided by official package it's not passible to do that. In stead, you can implement your own MarhalJSON method so that you can decide the position of your struct fields.
To the question "can I make a single struct type serialize its fields in a different order or different occasions ?" :
there isn't a simple way to do this.
Regarding struct fields : the code you write shows the assigning operations in a given order, but once your code is compiled, there is no trace of that order anymore.
If you really need this (side note : I would be curious to know about your use case ?), you could create a custom type, with its own .MarshalJSON() method, which would hold a value indicating "fields should be serialized in this order".
If what you need is to send an array of heterogeneous objects, use separate struct types, and an []interface{} array :
type Obj1 struct{
Key string `json:"name"`
Value string `json:"value"`
}
type Obj2 struct{
Value string `json:"value"`
Key string `json:"name"`
}
func main() {
test := []interface{}{ Obj1{Key: "test",Value: "wep"}, Obj2{Value: "wep",Key: "test"}}
bytes, _ := json.Marshal(test)
fmt.Print(string(bytes))
}
https://play.golang.org/p/TOk28gL0eSK

Check empty struct that have array fields

I have a nested (not embedded) struct for which some of field types are arrays.
How can I check if an instance of this struct is empty? (not using iteration!!)
Note that there can't use StructIns == (Struct{}) or by an empty instance! This code have this error:
invalid operation: user == model.User literal (struct containing model.Configs cannot be compared)
user.Configs.TspConfigs:
type TspConfigs struct {
Flights []Flights `form:"flights" json:"flights"`
Tours []Tours `form:"tours" json:"tours"`
Insurances []Insurances`form:"insurances" json:"insurances"`
Hotels []Hotels `form:"hotels" json:"hotels"`
}
Those are slices, not arrays. It's important to emphasize as arrays are comparable but slices are not. See Spec: Comparision operators. And since slices are not comparable, structs composed of them (structs with fields having slice types) are also not comparable.
You may use reflect.DeepEqual() for this. Example:
type Foo struct {
A []int
B []string
}
f := Foo{}
fmt.Println("Zero:", reflect.DeepEqual(f, Foo{}))
f.A = []int{1}
fmt.Println("Zero:", reflect.DeepEqual(f, Foo{}))
Output (try it on the Go Playground):
Zero: true
Zero: false

Nilable value in appengine/datastore using Go

The list of supported types by datastore doesn't contain pointer types (https://cloud.google.com/appengine/docs/go/datastore/reference).
How then can I represent a value that can and sometimes should be nil?
For example in the following structure I need the DailyValuePercent to be nilable to explicitly say that the value is missing.
type NutritionFact struct {
Name string `datastore:",noindex" json:"name"`
DailyValuePercent int `datastore:",noindex" json:"dailyValuePercent"`
}
Since I can't use *int as the field type for datastore then how to represent an optional value?
Either store your ints as strings (with empty string => no value) or use a composite type like:
type NillableInt struct {
i int
isNil bool // or isNotNil bool if you want different default semantics
}
Adapt to your performance vs. memory usage requirements.
If you want your code to deal with int pointers but persist nil values in the datastore, define your struct like this:
type NutritionFact struct {
Name string `datastore:",noindex" json:"name"`
DailyValuePercent int `datastore:"-"`
}
And implement the PropertyLoadSaver interface where you will save/load an int value and a isNil boolean.

Sort "array" of mixed data type in C

I have a continuous block of memory, where the first N bytes all contain objects of type A and the remaining bytes contain elements of type B. So for example, I might have 120 objects of type A followed by 40 objects of type B.
Type A and type B are both structures with different sizes, but both have an integer member "index" which is what I want to sort on. Basically I want to end up with an array that is sorted on index and I currently have one which is sorted on data type. Ideally, I'd like to end up with it sorted on index, then by type, so something like
Index==1 elements | Index==2 elements | ... | Index==L elements
Type A | Type B | Type A | Type B | ... | Type A| Type B
The only thing I've come up with so far is to sort the type A and type B blocks separately by index and then use memcopy to shuffle things around so they look like above. Is there a better solution?
How is the original array set up? Mixing different types in the same array seems like a bad idea. Is there a reason you need to have them in the same array?
If they must be in the same array you might want to use a union. Something like
enum myType { A, B };
struct typeA { myType type; int key; ... data ... }
struct typeB { myType type; int key; ... data ... }
union myTypes { typeA myA; typeB myB }
myTypes data[128];
You can now use the qsort function from the C library.
Another option would be to use a separate array of pointers to the objects and then sort that auxilary array. You would still need some kind of type field at the beginning of each struct though.
Instead of pointers as suggested, you might want to use a struct consisting of type and pointer (the latter even as a union of two different pointers). In this case, you can easily distinguish which type the objects are - unless they nevertheless have the ID field at the same place.
So suppose you have
struct typeA {
int whatever;
int id;
}
struct typeB {
double whatever;
int id;
}
you are bitten and have to do as I stated:
struct typptr {
enum type { typ_A, typ_B } type;
union {
struct typeA * Aptr;
struct typeB * Bptr;
}
}
int getID(struct typptr t)
{
if (t.type == typ_A) {
return (t.Aptr)->id * 2;
} else {
return (t.Bptr)->id * 2 + 1; // have B always sorted after A...
}
}
This way you can easily write a cmp function for qsort in order to sort the struct typptrs.
If the types are "shaped similiarly", such as
struct typeA {
int id;
int whatever;
}
struct typeB {
int id;
double whatever;
}
i.e. have the id field at the start, things are easier (but I don't know if this is portable) as you can always cast to one of them and read out the id field. So you only need an array of pointers and can omit the type field.
There's important information in your later comment - the types aren't initially mixed.
If so, you could run a sort phase on each array part individually (quicksort or any other method you'd like), and then do a final phase of merge-sort between the two arrays (assuming you can spare the additional space)
that's still NlogN + N = NlogN

Resources