Please note this is double curly braces in this format{}{}, and not nested curly braces {{}}. I am also unsure if this is an empty interface issue, a slice issue or a struct issue. I am guessing it is a combination of at least two of these.
I am learning Golang and I have reached empty interfaces. I see I need to declare a slice of empty interfaces as
[]interface{}{}
or for instance
[]interface{}{"aa","bb"}
I don't just want to blindly start using it. Whereas I understand the idea of empty interfaces, and that an interface contains two portions of data, the value and the type, I just don't understand the {}{} structure? I learned that slices are created with make() or for instance
[]int{}
What is the extra {} for when using empty interfaces?
Thank you
I have googled it, and went through my tutorials. I also compared it to what I know about structs as I suspect a interface is a struct. My attempts to google golang interfaces yields mainly normal interfaces, with which I have no problem.
[]interface{} is the type: a slice [] of empty interface interface{} (which is actually an anonymous inline type declaration). The second set of braces instantiates an instance of that type, so []interface{}{} is an empty slice of empty interface, []interface{}{"aa","bb"} is a slice of empty interface with two items. That could also be []string{"aa","bb"}, a slice of string with two items, which is the same thing with a different type (string in place of interface{}).
You could also have a non-empty interface, like []interface{SomeFunc()}{} being an empty slice of interface{SomeFunc()}, a non-empty anonymous interface type. Or you could do it with an anonymous struct type, like []struct{Foo string}{{"bar"},{"baz"}}. Here there's even more braces - the first pair around the type definition body, the second pair around the slice literal, and within that, one pair each around two struct literals.
interface{} is the empty interface type
[]interface{} is a slice of type empty interface
interface{}{} is an empty interface type composite literal
[]interface{}{} is a slice of type empty interface composite literals
The Go Programming Language Specification
Interface types
Slice types
Composite literals
Take the Go Tour: A Tour of Go
Related
Why does golang not support casting a slice to an empty interface? You can however work around it, by declaring a variable with an empty interface as type and assinging the slice to that variable. Why are those not the same thing?
Example: https://play.golang.com/p/r4LXmR4JhF0
First, Go doesn't support casting at all.
There simply is no type casting in Go*.
What you're attempting to do is a type assertion.
There are two reasons your attempt fails. Both are explained by the compiler:
invalid type assertion: slice.(<inter>) (non-interface type []interface {} on left)
You cannot type-assert any non-interface type to an interface.
non-name *castedSlice on left side of :=
*castedSlice is invalid in this context.
Assignment is the correct approach if you want to store a slice in a variable of type interface{}. You can do this a few ways:
As you have discovered, this works:
var result interface{}
result = slice
You can combine those two lines:
var result interface{} = slice
You can also do a short variable declaration:
result := interface{}{slice}
*lest anyone nitpick the statement: It is technically possible to accomplish the same as type casting in Go, with use of the unsafe package, but as this is outside of the language spec, and is, by definition, unsafe, I think it's still a reasonable statement that Go does not support type casting.
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".
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.
When I need methods on slices I have to declare a new type. But what should I name it?
type SliceSomething []Something or type SomethingSlice []Something?
Since it's read as "slice of something" the first one seems better, but autocomplete would probably prefer the second one.
The CodeReview wiki page
Variable names in Go should be short rather than long.
This is especially true for local variables with limited scope.
Prefer c to lineCount. Prefer i to sliceIndex.
The basic rule: the further from its declaration that a name is used, the more descriptive the name must be.
That is why you won't find "Slice" often in the go sources, except in:
encoding/gob/encoder_test.go:335: type recursiveSlice []recursiveSlice
encoding/json/encode_test.go:107: type renamedByteSlice []byte
encoding/json/encode_test.go:108: type renamedRenamedByteSlice []renamedByte
regexp/onepass.go:283: type runeSlice []rune
sort/sort.go:233: type IntSlice []int
sort/sort.go:243: type Float64Slice []float64
sort/sort.go:258: type StringSlice []string
unicode/maketables.go:1118: type runeSlice []rune
So if you have to put 'Slice' in the name, it would be type SomethingSlice []Something rather than type SliceSomething []Something.
Check out Go source code for generally recognized idioms.
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.