Why is it I can't have this in golang?
type EventDefinition struct {
Name string
EventProperties interface{}
}
Where EventProperties can be one of may types of structs, each struct with different fields. The idea is to have an EventDefinition with EventProperties
type Party struct {
Location string
Hour string
}
or
type Wedding struct {
Bride string
Groom string
Hour string
}
or
type Graduation struct {
Location string
Graduate string
}
Found my problem. The problem was not related to this issue, the problem was
Location : event.Party.Location.(string),
At some point in my implementation I was doing this when Location was a nil interface{}, hence the blowup.
As a response to this, it is possible to do what I mentioned.
Related
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 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
I have following data:-
{"me":[{"id": "0xcfd","Title":"Story of Stackoverflow","Users":[{"id":"1","Name":"MetaBoss"},{"id":"2","Name":"Owner"}],"Tag":"golang,programming"}]}
and I have the following struct:-
type Root struct {
ID string `json:"id,omitempty"`
Title string `json:"Title,omitempty"`
Myuser Users `json:"Users,omitempty"` // Users is struct
Tag string `json:"Tag,omitempty"`
}
type Users struct {
ID string `json:"id,omitempty"`
Name string `json:"Name,omitempty"`
}
To unmarshal the data, I am trying to do following things -
type Unmarh struct {
Me []Root `json:"me"`
}
var r Unmarh
err = json.Unmarshal(response, &r)
while printing r.Me[0].Myuser, I am not able to get data.
I am getting below error -
json: cannot unmarshal array into go struct field Root.Myuser of type User struct {....Users struct data}
It needs Myuser to be multidimensional array type and not Users struct. I have no Idea, how to represent Users multidimensional array inside struct
In the json the Users key is an array and so the corresponding Go field should be a slice.
type Root struct {
ID string `json:"id,omitempty"`
Title string `json:"Title,omitempty"`
Users []User `json:"Users,omitempty"`
Tag string `json:"Tag,omitempty"`
}
https://play.golang.org/p/azE7kPFs02V
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.
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.