Is there a shortcut for assigning a variable to a pointer without creating the variable in a separate line first? - go

If I have a struct like this:
type Message struct {
Id int64
Message string
ReplyTo *int64
}
And then if I did create an instance of this struct like this:
var m Message
m.Id = 1
m.Message = "foo bar yo"
var replyTo = int64(64)
m.ReplyTo = &replyTo
Then it would work.
But I was wondering if there was a shortcut for the last step?
I tried doing something like:
m.ReplyTo = &int64{64}
But it did not work.

I don't think you can because the value is a primitive and attempting to do it in one shot like the below would be a syntax error. Its attempting to get an address of a value so it wouldn't be possible. At least I am not aware of a way where its possible.
someInt := &int64(10) // would not compile
The other alternative you have is to write a function to return a pointer to the primitive like the following:
func NewIntPointer(value int) *int {
return &value
}

A tricky way to get int pointer without create new variable.
someIntPtr := &[]int64{10}[0]

Related

How to get a struct tag without having to instantiate the struct

type User struct{
Name string `json:"name"`
}
func main() {
t := reflect.TypeOf(User{})
}
It is possible to capture the tag's values ​​without instantiating it. For example capturing the value of the tag "json" without having to instantiate the User structure.
Creating a value is not a performance issue in almost all scenarios, but you can avoid creating a value by using a nil pointer value.
t := reflect.TypeOf((*User)(nil)).Elem() // Elem "dereferences" the pointer type.
The reason to use the pointer pattern shown here is that the one syntax works with every type. In particular, it handles interface types:
type I interface{}
// Naive developers might expect the following
// to return the type for I, but it actually
// returns nil.
t := reflect.TypeOf(I(nil))
// The pointer pattern returns the type for I.
t = reflect.TypeOf((*I)(nil)).Elem()
The pointer syntax is the same for all types independent of how the zero value is written for the type:
t = reflect.TypeOf(User{})
t = reflect.TypeOf(uint(0))
t = reflect.TypeOf(myString(""))
Use t = reflect.TypeOf((*T)(nil)).Elem() where T is any type:
t = reflect.TypeOf((*User)(nil)).Elem()
t = reflect.TypeOf((*uint)(nil)).Elem()
t = reflect.TypeOf((*myString)(nil)).Elem()

Why must I pass type to make function when variable is already declared?

I want use anonymous struct to do something.
var users []struct{
Name string `json:"name,omitempty"`
Age int
}
and I have to write the type again to set value
users = make([]struct{
Name string `json:"name,omitempty"`
Age int
}, 0, 10)
if I insist using anonymous struct, is there any way to make it more decent?
(if no, I wonder why golang design make function like this...)
Anonymous structs are handy for one-time use.
If you are using it more than once, then define a named struct type.
If you only use it within a single function, you can define the type within the scope of that particular function, so it's obvious that it cannot be used elsewhere:
func myfunc() {
type MyType struct {
Name string
}
m := MyType{Name: "Hello, World!"} // this type can only be used within this func
fmt.Println(m)
}
if I insist using anonymous struct, is there any way to make it more decent?
Yes, there is. Use :=:
users := make([]struct{
Name string `json:"name,omitempty"`
Age int
}, 0, 10)
Of course, this only works if you're calling make right after you're defining the variable. If these bits are separated by other code, this trick won't work for you.
But don't be afraid to name your types. That's generally a better approach anyway (with or without :=).

Creating map with empty values

I need to use a map for keys only, I don't need to store values. So I declared a map like this:
modified_accounts:=make(map[int]struct{})
The idea is to use empty struct because it doesn't consume storage.
However, when I tried to add an entry to the map,
modified_accounts[2332]=struct{}
I got a compile error:
./blockchain.go:291:28: type struct {} is not an expression
How do I add an empty key and no value to the map ?
You can do it declaring a empty variable
var Empty struct{}
func foo() {
modified_accounts := make(map[int]struct{})
modified_accounts[2332] = Empty
fmt.Println(modified_accounts)
}
Or creating a new struct every time
func bar() {
modified_accounts := make(map[int]struct{})
modified_accounts[2332] = struct{}{}
fmt.Println(modified_accounts)
}
To create a empty struct you should use struct{}{}
The error is exactly what you see in the below line :
./blockchain.go:291:28: type struct {} is not an expression
An expression is something that evaluates to something (something that has a value), struct{} is a type, and your statement is trying to assign a type(right) to a map's key's value, a variable(left)
What you need is to create a variable of this type, and assign that variable to the map's key as a value.
Either by using :
var x struct{}
modified_accounts[2332] = x
or
modified_accounts[2332] = struct{}{}
In either of the above way, you are creating a value of type struct{}, and assigning that value to the map's key.

cannot assign to struct field in map

I would like to set a default value and if this is not set in a structure, I would like to set it. It's a bit confusing, but please take a look to the (simplified) code:
package main
import "log"
type Something struct {
A string
B map[string]Type
C Epyt
}
type Type struct {
A Epyt
B string
}
type Epyt struct {
A string
B string
}
func main() {
var a Something
a.A = "Test A (Something)"
// var a.B["one"] Type
a.B["one"].A.A = a.B["one"].A.A
a.B["one"].A.A = "Test A ([one]Type.Epyt)"
a.B["two"].A.A = "Test A ([two]Type.Epyt)"
a.C.A = "Test A (Epyt)"
a.C.B = "Test B (Epyt)"
for i := range a.B {
if a.B[i].A.B == "" {
a.B[i].A.B = a.C.B
}
}
log.Printf("%+v", a)
}
I'm working with viper to unmarshal a config file, therefor I'm not able to use pointers (or am I wrong?).
The error I'm getting, is cannot assign to struct field *** in map.
I found that this is an old bug in go lang still not corrected.
I've read Why do I get a "cannot assign" error when setting value to a struct as a value in a map? and Golang: I have a map of structs. Why can't I directly modify a field in a struct value? but as I said, I can't operate with pointers (or?), therefor please don't mark this as duplicate as it is not!
If someone has an idea on how to do this right, please help!
I played around a bit and got it working! I thought there is an error, because if I use printf over the whole structure, I get the address instead of the value back. Sorry for the inconvenience!
As #mkopriva told me, I tried to use pointers. After some errors I got it to work so far! Sorted out this brain bug ;)
Thank you again!
You haven't initialised the map.
Try
var a Something
a.B = make(map[string]Type)
Also, none of the structures you're referring to exist.
Ie, instead of:
a.B["one"].A.A = ...
You should do:
a.B["one"] = Type{
A: Epyt{
A: "test",
B: "foo",
},
B: "something",
}

What's happening with these pointers?

I wrote some odd code, but I'm not sure why it works and what I can learn from it. I have a slice type build from another struct. I made a function on the slice type to modify itself. To do this, I seem to have to throw around *'s a little much.
I'm trying to learn about pointers in Go and would like a little help. Here's an example (http://play.golang.org/p/roU3MEeT3q):
var ClientNames = []string {"Client A", "Client B", "ClientC"}
type InvoiceSummaries []InvoiceSummary
type InvoiceSummary struct {
Client string
Amt int
}
func (summaries *InvoiceSummaries) BuildFromAbove() {
for _, name := range ClientNames {
*summaries = append(*summaries, InvoiceSummary{name, 100})
}
}
My question is: What is the purpose for each of these * and why am I not using any &?
What is the purpose for each of these * ?
By making the method receiver as pointer, you could easily change the property of the object. I think that's one of the benefit. This example below will prove it.
package main
import "fmt"
type someStruct struct {
someVar int
}
func (s someStruct) changeVal1(newVal int) {
s.someVar = newVal
}
func (s *someStruct) changeVal2(newVal int) {
s.someVar = newVal
}
func main() {
s := someStruct{0}
fmt.Println(s) // {0}
s.changeVal1(3)
fmt.Println(s) // {0}
s.changeVal2(4)
fmt.Println(s) // {4}
(&s).changeVal2(5)
fmt.Println(s) // {5}
}
and why am I not using any &?
Pointer method receiver is quite special, it can also be called from non-pointer struct object. Both of s.changeVal2(4) and (&s).changeVal2(5) are valid & will affect the value of someVar.
Example http://play.golang.org/p/sxCnCD2D6d
You have to use a pointer for the receiver - (summaries *InvoiceSummaries) - because otherwise the argument is passed by value, having a pointer means you pass a reference to the value instead. If not for that, then you couldn't modify the collection at all.
Inside of the methods body you have use * because it is the dereferncing operator and returns the value at the address. Ampersand (&) is the opposite, it gives the address of a value.
Nothing wrong with your code but normally addresses to slices aren't used. A slice is a small struct that gophers are normally happy to pass by value. If a method or function is creating a new slice, the gopher is happy to return the new slice, by value again, as the return value.
Of course passing a slice by value doesn't guarantee anything about the backing store remaining unchanged when the method/function returns. So it can't be used as a way of guaranteeing the data elements of the slice haven't mutated.

Resources