Why do struct declarations sometimes contain blank fields? - go

From the golang spec
// A struct with 6 fields.
struct {
x, y int
u float32
_ float32 // padding
A *[]int
F func()
}
Are there any practical scenarios of using the blank _ fields inside a struct? (some code snippets would be appreciated)

The padding is exactly what it is called: Some padding to align the following field to your needs, e.g. to match the layout of a C struct. It cannot be accessed (at least not without package unsafe).

Related

How does unkeyed literals prevention work

Per this doc
type Point struct {
X, Y float64
_ struct{} // to prevent unkeyed literals
}
For Point{X: 1, Y: 1} everything will be fine, but for Point{1,1} you will get a compile error:
./file.go:1:11: too few values in &Pointer literal
Then I tried it in another data type _ byte and _ func() as below
type Pointer struct {
X, Y int
//_ byte // to prevent unkeyed literals
//_ func() // to prevent unkeyed literals
}
Both of them could prevent unkeyed literals. How does it prevent unkeyed literal? Is _ struct{} more efficient?
Unkeyed structs require you to specify all struct keys; it is an error if you don't specify the value for Y for example:
type Point struct {
X, Y float64
}
_ = Point{1}
// Output:
// ./main.go:8:8: too few values in Point{...}
The _ struct{} field doesn't really prevent unkeyed literals from the same package, as you can still do:
type Point struct {
X, Y float64
_ struct{} // to prevent unkeyed literals
}
_ = Point{1, 2, struct{}{}}
// Ugly and weird, but valid!
But in order to be able to assign values in struct fields from other packages they need to be "exported", that is, start with a capital letter, and _ doesn't, so this is an error:
_ = x.Point{1, 2, struct{}{}}
// Output
// ./main.go:6:28: implicit assignment of unexported field '_' in x.Point literal
There is nothing special about _; you can use anything else that doesn't start with a capital as well, such as noexport struct{} or whatnot.
Why struct{} and not byte or int? Well, those types allocate some amount of memory; for an int it's usually 8 bytes (or 4 bytes on a 32bit system), and byte is an alias for uint8 and allocates one byte.
struct{} on the other hand is an "empty" type (you can't assign anything to it) and won't use any memory. This is a very small optimisation, but if you're going to type something you might as well type struct{}.
Is all of this worth it? In my opinion it's not; if someone wants to use unkeyed struct literals with your library then that's their choice. Many lint tools will already warn on this, including the built-in go vet:
$ go vet main.go
./main.go:8:6: net/mail.Address composite literal uses unkeyed fields
How does it prevent unkeys literals works?
An unkeyed struct literal must specify all fields; by adding a field that cannot be specified from outside the package, it makes it impossible to use this format, so it requires a keyed literal. "Keyed" or "unkeyed" refers to whether the field names appear in the struct literal.
Does _ struct{} more efficient?
Yes, because it has a width of zero, so it doesn't consume any memory. All other types would increase the memory footprint of the struct unnecessarily.

Typecasting structs with same underlying types

For basic types we can easily cast the types if their underlying types are same .But the fields inside struct with same memory layout cannot be easily cast from one to another type.
There is a proposal for this problem unfortunately it got rejected .After an hour of googling with no luck I came here seeking the help from experts.
Look at example below
:
package main
import (
"fmt"
)
type Int int
type A struct {
name string
age Int
}
type B struct {
name string
age int
}
func main() {
var a A= A{"Foo",21}
var b B= B{"Bar", 21}
fmt.Println(a,b,(A)(b)) //Error here as expected
}
Eventhough struct A and B has the same underlying type of struct { string,int} why cannot I cast to each other as the underlying type of Int is int.
Whether it is possible to cast recursively unless the underlying type differs?
You can't do it simply because the language spec does not allow it. Regarding structs, you can only convert from one type to the other if Spec: Conversion:
A non-constant value x can be converted to type T in any of these cases:
...
ignoring struct tags (see below), x's type and T have identical underlying types.
If you're absolutely sure the structs' memory layout is identical, you may use an unsafe conversion (using package unsafe) like this:
var a A = A{"Foo", 21}
var b B
b = *(*B)(unsafe.Pointer(&a))
fmt.Println(a, b)
This will output (try it on the Go Playground):
{Foo 21} {Foo 21}
But use this as the last resort. Using unsafe you lose compile time type safety and portability guarantees. E.g. if later you only modify one of the structs, the above code will continue to compile even though it might not be correct anymore, and the compiler will not able to inform you about that.

How to convert a struct to a different struct with fewer fields

I am trying to copy a struct of type Big to type Small without explicitly creating a new struct of type Small with the same fields.
I have tried searching for other similar problems such as this and this yet all the conversions between different struct types happen only if the structs have the same fields.
Here is an example of what I tried to do:
// Big has all the fields that Small has including some new ones.
type Big struct {
A int
B string
C float
D byte
}
type Small struct {
A int
B string
}
// This is the current solution which I hope to not use.
func ConvertFromBigToSmall(big Big) Small {
return Small{
A: big.A,
B: big.B,
}
}
I expected to be able to do something like this, yet it does not work:
big := Big{}
small := Small(big)
Is there a way of converting between Big to Small (and maybe even vice-versa) without using a Convert function?
There is no built-in support for this. If you really need this, you could write a general function which uses reflection to copy the fields.
Or you could redesign. If Big is a Small plus some other, additional fields, why not reuse Small in Big?
type Small struct {
A int
B string
}
type Big struct {
S Small
C float
D byte
}
Then if you have a Big struct, you also have a Small: Big.S. If you have a Small and you need a Big: Big{S: small}.
If you worry about losing the convenience of shorter field names, or different marshalled results, then use embedding instead of a named field:
type Big struct {
Small // Embedding
C float
D byte
}
Then these are also valid: Big.A, Big.B. But if you need a Small value, you can refer to the embedded field using the unqualified type name as the field name, e.g. Big.Small (see Golang embedded struct type). Similarly, to create a Big from a Small: Big{Small: small}.
Is there a way of converting between Big to Small (and maybe even vice-versa) without using a Convert function?
The only option is to do it manually, as you have done. Whether you wrap that in a function or not, is a matter of taste/circumstance.
you can do something like this:
package main
import (
"fmt"
)
type Big struct {
Small
C float32
D byte
}
type Small struct {
A int
B string
}
func main() {
big := new(Big)
big.A = 1
big.B = "test"
big.C = 2.3
fmt.Printf("big struct: %+v", big)
fmt.Println()
small := big.Small
fmt.Printf("small struct: %+v", small)
fmt.Println()
}
output:
big struct: &{Small:{A:1 B:test} C:2.3 D:0}
small struct: {A:1 B:test}
playgroundlink:https://play.golang.org/p/-jP8Wb--att
I'm afraid there is no direct way to do that. What you did is the right way.
You can try to write the first object to JSON and then try to parse it back to the second object. Though, I wouldn't go this way.
One more way, which is a specific one is that the Big object will inherit the Small object. then you can downcast. Again, I wouldn't do that but if you must...

Golang How to extract the sizeof struct to int

I'm starting to learn golang but come across what I hope is a simple problem.
I have a file written to in C with several structs. ie myStruct's
Now I want to read one struct of data from this file.
In C I simple open a file and move the fileptr number of structs * sizeofStruct. Like this
int sizeofStruct = sizeof(myStruct)
seek(filehandle, searchNo*sizeofStruct)
read(filehandle, &data, sizeofStruct)
This doesn't seem to be as simple in Golang as "sizeof"... rather multiple conversions ending up in uintptr... something, or reflect.int32()
var spect Spectrum // struct Spectrum
const SizeOfSpectrum = unsafe.Sizeof(spect)
I was hoping SizeOfSpectrum would contain equal to sizeof(spect) in C
Can you guys help me to get the size of a struct in an int variable?
I have a file written to in C with several structs. ie myStruct's Now
I want to read one struct of data from this file. In C i simple open a
file and move the fileptr number of structs * sizeofStruct.
I haven't found a way to get the numeric value and multiply with
another, say int16 value. Purpose is to seek a position within the
file.
You do the same thing in Go, using explicit conversions.
For example,
package main
import (
"fmt"
"unsafe"
)
func main() {
type S struct{ F int32 }
i16 := int16(42)
// The Go Programming Language Specification
// https://golang.org/ref/spec
// Numeric types
// Explicit conversions are required when different
// numeric types are mixed in an expression or assignment.
// func (f *File) Seek(offset int64, whence int) (ret int64, err error)
offset := int64(i16) * int64(unsafe.Sizeof(S{}))
fmt.Println(offset)
}
Playground: https://play.golang.org/p/YFyU11Lf2qc
Output:
168

Any difference in using an empty interface or an empty struct as a map's value?

I am using this construct to simulate a set
type MyType uint8
map[MyType]interface{}
I then add in all my keys and map them to nil.
I've learnt that it is also possible to use
map[MyType]struct{}
Any benefits of using the empty struct versus interface{}.
Memory usage. For example, types struct{}, interface{}, and bool,
package main
import (
"fmt"
"unsafe"
)
func main() {
var s struct{}
fmt.Println(unsafe.Sizeof(s))
var i interface{}
fmt.Println(unsafe.Sizeof(i))
var b bool
fmt.Println(unsafe.Sizeof(b))
}
Output (bytes for 32-bit architecture):
0
8
1
Output (bytes for 64-bit architecture):
0
16
1
References:
Go Data Structures: Interfaces
The empty struct and empty interface, though syntactically similar, are actually opposites. An empty struct holds no data; an empty interface can hold any type of value. If I see a map[MyType]struct{}, I know immediately that no values will be stored, only keys. If I see a map[MyType]interface{}, my first impression will be that it is a heterogenous collection of values. Even if I see code storing nil in it, I won't know for sure that some other piece of code doesn't store something else in it.
In other words, using struct{} makes your code much more readable. It also saves a little memory, as described in the other answer, but that is just a fringe benefit of using the right tool for the job.
I would like to add additional detail about empty struct , as differences are already covered by andybalholm and peterSO .
Below is the example which shows usability of empty struct .
Creates an instance of rectangle struct by using a pointer address
operator is denoted by & symbol.
package main
import "fmt"
type rectangle struct {
length int
breadth int
color string
}
func main() {
var rect1 = &rectangle{10, 20, "Green"} // Can't skip any value
fmt.Println(rect1)
var rect2 = &rectangle{}
rect2.length = 10
rect2.color = "Red"
fmt.Println(rect2) // breadth skipped
var rect3 = &rectangle{}
(*rect3).breadth = 10
(*rect3).color = "Blue"
fmt.Println(rect3) // length skipped
}
Reference : https://www.golangprograms.com/go-language/struct.html
For a thorough read you can refer : https://dave.cheney.net/2014/03/25/the-empty-struct

Resources