This question already has answers here:
Declare a constant array
(5 answers)
Closed 3 years ago.
I have a type A that is basically a simple map:
type A map[int32]struct{}
Now, I would like to have a special value of this type to be able to treat it a bit differently. I thought that it would be smart to use nil for this propose (additionally, this way, all non initialized variables of type A would have this value, and this is also what I would like to have):
const s A = nil
But I got
const initializer cannot be nil
Sure I can accept this and refactor my program in dozens of different ways. But I'm still wondering why it's impossible to initialize const to nil? There must be an architectural reason but I don't see it.
(Note that I prefer to "rename" nil instead of using it directly only because the name nil is not very intuitive in my case.)
I believe that it is because you can only have constants of type boolean, rune, integer, floating-point, complex, and string.
Docs: https://golang.org/ref/spec#Constants
Whereas nil is a zero-value for types pointer, interface, map, slice, channel and function
Docs: https://golang.org/ref/spec#The_zero_value
You can read more here https://blog.golang.org/constants
Related
This question already has answers here:
When to use pointers [duplicate]
(1 answer)
I don't understand when to use pointers on go [duplicate]
(2 answers)
Difference between returning a pointer and a value in initialization methods [duplicate]
(1 answer)
Pointers vs. values in parameters and return values
(5 answers)
Golang struct initialization
(2 answers)
Closed 15 days ago.
I am wondering what the differences are between those two ways of initializing a struct in Go. Does the second one give you a pointer storing the address of the struct? But they have the same syntax if we want to change the field variables, so how are they different?
I can de-reference the pointer, apparently. But do they have different functionalities? In what scenario would I prefer one over the other?
b := Student{Name:"Bob"}
pb := &Student{Name:"Bob", Age:8,}
They only differ in what the type of the local variable is. Whether to prefer one over the other depends entirely on how you would use that variable in the remainder of the function's body. If you are always passing it around (meaning use it on the right-hand side of an assignment, as an argument to a function call, or returning it) as a pointer, use the pb := &Student{...} form. If you intend to create (shallow) copies of it, the b := Student{...} form might be more convenient. This is however purely based on the fact that typing pb is easier than &b, and that typing b is easier than *pb. If you apply these substitutions everywhere (except for in the context of field accesses, where it is allowed but not mandatory, see below), they are completely interchangeable.
If you want to be able to set the variable holding the struct (pointer) to nil, use a pointer, obviously. But this can also be solved by introducing a new, pointer-typed variable and setting that to either nil or &b.
Some types in Go cannot be copied (this is typically accomplished by embedding a [0]sync.Mutex field in the struct, which takes up no space but triggers the "mutex copy" error of the compiler). An example would be protobuf structs. For these, it is almost always preferable to use the pointer form; however, this is not required, as the initialization via b := Student{...} is not a copy.
Go allows transparently dereferencing when accessing struct fields. b.Name, (&b).Name, pb.Name, (*pb).Name all work and are equivalent. Note however that transparent dereferencing only works over one level, (&pb).Name will result in a compiler error.
The composite literals differ in the initialization of the Age field. The first sets the field to the zero value. The second sets the field to the number 8. Otherwise, the initialization of the struct values is identical.
What happens next is where the key difference lies. The first example assigns the value to a variable named b. The second example takes assigns the value to an anonymous variable; takes the address of the variable; and assigns the result to a variable named pb.
The type of b is the struct type and the type of pb is a pointer to the struct type.
See I don't understand when to use pointers on go to see a discussion on why one might want to use a pointer.
This question already has answers here:
Please explain &, and * pointers
(6 answers)
Is it correct to use slice as *[]Item, because Slice is by default pointer
(1 answer)
Closed 4 months ago.
while looking into code I found below function declaration
func (c *Congress) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, uncles []*types.Header, receipts *[]*types.Receipt, systemTxs []*types.Transaction) error {
where two parameters are txs *[]*types.Transaction, uncles []*types.Header, what does it mean in terms of golang
just want to understand golang terminology with reference to above code
uncles []*types.Header
uncles is slice. If you copy it somewhere (perhaps by passing it in as a function parameter) updates to it will not propagate backwards to the original (with the nuance that changes to elements will propagate, but the size/data pointer of the original will remain unchanged).
txs *[]*types.Transaction
txs is a pointer to a slice. It’s sort of like a “reference” in that updates to the slice pointed at propagate to anyone else pointing to that slice. So if you pass a pointer to a slice as a function parameter, the function may change the properties of the slice pointed to (adding/removing elements).
This question already has answers here:
Typecasting in Golang
(5 answers)
Closed 2 years ago.
Reading this https://github.com/go-pg/pg/wiki/Writing-Queries#select I see many times this expression:
(*Book)(nil)
Example:
count, err := db.Model((*Book)(nil)).Count()
What does it mean?
That is a type conversion. Assuming the db.Model function takes interface{}, it sends an nil interface of type *Book to the function.
To convert a value v to type Book, you'd write:
Book(v)
However, you cannot write Book(nil) because nil is a pointer and Book is not. If you had a type
type BookPtr *Book
Then you could've written BookPtr(nil). Extending that, you want to write *Book(nil), but that means *(Book(nil)) which is invalid, hence:
(*Book)(nil)
'nil' is to Go what NULL/null is to other languages like C#/Java, etc. The *Variable is just getting the pointer value for the Book object of Model.
So in this case, I believe what's happening here is that (*Book)(nil) is setting the pointer value of the Book object of the Model to nil(/null).
Hope this helps in some way. 😊
Good Resource: https://go101.org/article/nil.html
This question already has answers here:
Multiple values in single-value context
(6 answers)
Closed 7 years ago.
Is there any way in Go to do this:
segment := Segment{
CumulativeDistanceMm: strconv.Atoi(record[9]),
Length: strconv.Atoi(record[1]),
LinkId: strconv.Atoi(record[8]),
SegmentId: strconv.Atoi(record[2]),
}
The error that I get is that strconv.Atoi returns multiple values so I can't assign it directly to the struct properties. If it was a variable I could use the underscore to ignore the second value. Can I do something similar for structs?
strconv.Atoi can fail and you have to deal with this failure. If such failures are absolutely impossible you would write a function func MustAtoi(s string) int which panics on failure and use that one in your struct initialization.
In Go doing some programming instead of using syntactical sugar or fancy syntax is common.
Most probably you should rethink your error handling.
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.