Structs with variations - idiomatic way to represent - go

What is the best idiomatic way to represent a struct which has variations for types ?
For example, say I have:
type A struct {
This []string
That int32
}
But I might also need to represent it as:
type A struct {
This string
That int32
}
Is there an idiomatic way to represent both variations with a single type ?

To me if your structure is able to accept a slice of This at any point in time then the first definition should always be the one you go for since a single item can be seen as a subset of a collection.
You could add functions to this structure to make it easier for the developers to interact with the structure though, but to me this looks fine as it is.

Related

Polymorphism without methods in go

Note: I'm editing this question to a concrete example of why I want to do this, which is why some of the answers might no longer make sense in context.
I am writing a bit of code that passes data from an input. The data is in the form of tags that have an identifier of what kind of data they contain and then the data.
Unfortunately I have no control over the input and don't know in advance what tags will be in it, one might be an int another might be a string, yet another might be an array of ints.
The problem arises when I need to handle all tags like the same type, for instance if I have a slice of tags, of a function that either accepts or returns a tag.
The solutions I have so far seen to this is to define the slices/functions with an empty interface which would allow me to do so, however that is kinda undesirable as it would not tell anything to other people using the package about what types are expected and also kinda defies the point of having a typed language in the first place.
Interfaces does however seem to be the solution here, and i would love to have a Tag interface to pass around, that does require though that I define methods on them, and there are really no methods they need.
My current solution looks like this
type Tag interface{
implementTag()
}
type TagInt int
func (tag TagInt) implementTag() {}
type TagString string
func (tag TagInt) implementTag() {}
While this does indeed work and solves my problem, having to define dummy methods just for that feels very wrong.
So my question sums up in this: Are there any way that I can define that something is a Tag without having to define dummy methods?
And now want to make a slice that can hold both t1 and t2 but nothing else.
You cannot do that. Sorry.
What I would do in your scenario is accept any type in the parameters with an empty interface then use a type assertion inside to confirm that it's the type that you want.
if t1, ok := interfaceInput.(t1); !ok{
// handle it being the wrong type here
return
}
Also if you want the tight coupling between a data type and it's method, namely an object, what's so wrong with having it be a method of the object?
You can use []interface{} for a "slice of any type" but then it's up to you to use type assertions and/or type switches to discover the actual runtime types of that slice's members.
Learn more about empty interfaces in the Tour of Go
And now want to make a slice that can hold both t1 and t2 but nothing
else.
This is quite an unusual requirement and you're unlikely to need this in Go. But you could also do your own discriminated union with:
type item struct {
typeSelector int
t1Value t1
t2Value t2
}
And then use []item, checking typeSelector at runtime to see which value is populated.
Alternatively you could even use *t1 and *t2 and have nil signify "no value in this field".

Assigning types to variables in Go

How to have a variable whose type is a variable type?
What do I mean by that? I have a python and java background. In both languages I can do things like assigning a class name to variable.
#Python
class A:
def __init__(self):
self.a = "Some Value"
# And asigning the class name to a variable
class_A = A
# And create instance from class A by using class_A
a = class_A()
Is there such a mechanism in go that allows me to do that? I couldn't know where to look at for such things in their documentation. Honestly, generally I don't know what these are called in programming languages.
For example I would like to be able to do:
// For example, what would be the type of myType?
var myType type = int
I will use this mechanism to take "type" arguments. For example:
func Infer(value interface{}, type gotype) {...}
Is there such a mechanism in go that allows me to do that?
The short answer is: No.
The long answer is: This sounds like an XY Problem, so depending on what you're actually trying to accomplish, there may be a way. Jump to the end to see where I address your specific use-case.
I suspect that if you want to store a data type in a variable, it's because you either want to compare some other variable's type against it, or perhaps you want to create a variable of this otherwise unknown type. These two scenarios can be accomplished in Go.
In the first case, just use a type switch:
switch someVar.(type) {
case string:
// Do stringy things
case int:
// Do inty things
}
Semantically, this looks a lot like assigning the type of someVar to the implicit switch comparison variable, then comparing against various types.
In the second case I mentioned, if you want to create a variable of an unknown type, this can be done in a round-about way using reflection:
type := reflect.TypeOf(someVar)
newVar := reflect.New(type).Interface()
Here newVar is now an interface{} that wraps a variable of the same type as someVar.
In your specific example:
I will use this mechanism to take "type" arguments. For example:
func Infer(value interface{}, type gotype) {...}
No, there's no way to do this. And it actually has much less to do with Go's variable support than it does with the fact that Go is compiled.
Variables are entirely a runtime concept. Function signatures (like all other types in Go) are fixed at compilation time. It's therefore impossible for runtime variables to affect the compilation stage. This is true in any compiled language, not a special feature (or lack thereof) in Go.
Is there such a mechanism in go that allows me to do that?
No there is not.
Use the empty interface:
var x, y interface{}
var a uint32
a = 255
x = int8(a)
y = uint8(a)
Playground example

Should we prefer to using the struct pointer for the list in Golang?

I have a question regarding the array of struct, if we should prefer to using the struct pointer or not.
Let's say we have Item and Cart which contains an array of Items.
type Item struct {
Id string
Name string
Price string
}
type Cart1 struct {
Id string
Items []Item
}
or
type Cart2 struct {
Id string
Items []*Item
}
I heard that when we append a struct to a struct list, golang will make a copy and add it to list, this is not necessary, so we should use list of struct pointer, is that true?
could anyone clarify?
You are right in your assumption - any(not only append()) function application copy by value provided arguments in Go. But how slice of pointer would reduce memory consumption? You should store actual struct plus reference to it in memory. Referencing is more about access control.
foo := cart1.Items[0]
foo.Name := "foo" //will not change cart1
//but in pointer case
bar := cart2.Items[0]
bar.Name := "bar" //will change cart2.Items[0].Name to "bar"
Go Arrays are passed by value, go Slices are passed by reference like a pointer. In fact slices include a pointer as part of their internal data type. Since your cart will have a variable number of items, just use []Item.
See this effective go reference
BTW if the slice has capacity 4 and you append something 5th thing to it, Go doubles the capacity, so it's not like every single addition will assign memory
As I understand your question, you problem is not memory consumption but unnecessary copying of structs.
Everything in Go is passed by value. If you have a slice of structs and you append a new struct Go will make a copy. Depending on the size of the struct it may be too much. Instead you may choose to use a slice of pointers to structs. That way when you append Go will make a copy of a pointer.
That might be cheaper but it also may complicate the code that will access the slice. Because now you have shared mutable state which is a problem especially in Go where you can't have a const pointer and anyone could modify the struct. Pointers are also prone to nil dereference errors.
Which one you choose is entirely up to you. There's no single "Go way" here.

Should I always use pointers when having a struct which contains others structs?

We have:
type A struct {
Name string
Value string
}
type B struct {
//
First *A
Second A
}
First off: What it is more efficient in B, using *A or A?
And second: When instantiating B I would use b := &B{ ... }, and thus have a pointer to B. All functions which have B as receiver use func (*B) ... as signature, therefore operating only on the pointer. Now that I always have a pointer to B, does it really matter what B is composed of? If I always use the pointer, no matter what fields B has, I always pass around a pointer to B and the value of Second A is never copied when passing *B around. Or am I missing something?
There is no single right answer. It always depends on your use case.
Some guidance:
Treat semantic reasons over efficiency considerations
Use a pointer when A is "large"
Avoid a pointer when B should not be allowed to edit A
Your second statement is correct. But when you have lots of instances of B using a pointer will be significantly more efficient (if the struct A is significantly bigger than the size of a pointer).
If you are in doubt, measure it for use case and then decide what the best solution is.
Just want to add to Sebastian's answer: use *A if you ever want it to be nil. This has benefits sometimes when marshaling JSON or using the struct with databases.
A non-pointer to a A will always have at least the zero value for that type. So it will always serialize into JSON even if you don't have anything useful there. To include it in the JSON serialization only when a populated struct is present, make it a pointer, which can be nil.

using new vs. { } when initializing a struct in Go

So i know in go you can initialize a struct two different ways in GO. One of them is using the new keyword which returns a pointer to the struct in memory. Or you can use the { } to make a struct. My question is when is appropriate to use each?
Thanks
I prefer {} when the full value of the type is known and new() when the value is going to be populated incrementally.
In the former case, adding a new parameter may involve adding a new field initializer. In the latter it should probably be added to whatever code is composing the value.
Note that the &T{} syntax is only allowed when T is a struct, array, slice or map type.
Going off of what #Volker said, it's generally preferable to use &A{} for pointers (and this doesn't necessarily have to be zero values: if I have a struct with a single integer in it, I could do &A{1} to initialize the field). Besides being a stylistic concern, the big reason that people normally prefer this syntax is that, unlike new, it doesn't always actually allocate memory in the heap. If the go compiler can be sure that the pointer will never be used outside of the function, it will simply allocate the struct as a local variable, which is much more efficient than calling new.
Most people use A{} to create a zero value of type A, &A{} to create a pointer to a zero value of type A. Using newis only necessary for int and that like as int{} is a no go.

Resources