Initialize a variable over a function by reference in golang - go

If I have a function which takes a reference as an argument and I want to use that function to initialize a variable I need to do this inside the init() function. That solution works, but it smells not really correct to me.
Is there another way to initialize a variable for a package in go like to use the init() function?
I think that there must be a better way. I thought already about a wrapping function, but that makes the logik not better.
I prepared a short and simple example
package main
import (
"fmt"
)
var a string
//A use of a function is not allowed
//foo(&a)
//Need to call init
func init() {
foo(&a)
}
func main() {
fmt.Println(a)
}
func foo(b *string) {
*b = "abc"
}
https://play.golang.org/p/GdBiDFB1KAe

That's fine, or you can just make a pointer and assign it like this:
var a = make("abc")
func main() {
fmt.Println(*a)
}
func make(s string) *string {
return &s
}
playground

Related

Change value of pointered argument inside a function

I'm stuck on something that seems/should be easy in Go.
I wrote a small go playground to explain my problem more easily => https://play.golang.org/p/Sm0SzrvEZS_o
package main
import (
"github.com/sirupsen/logrus"
)
type toto struct {
name string
}
func transform (data ...interface{}) {
logrus.Info("data before ", data)
data[0] = "tutu"
logrus.Info("data after ", data)
}
func main() {
var titi toto
logrus.Info("titi before ", titi) // -> empty
transform(&titi)
logrus.Info("titi after ", titi) // -> should have a name but don't
}
The goal is to pass a struct to a function, modifying in it and continue to use it in the caller function. Sadly, the argument is modified inside the child function but don't move into the caller.
I'm a beginner in this language, maybe I just missed something somewhere... Many thanks in advance for your help
This seems to do it:
package main
type toto struct { name string }
func transform (data ...interface{}) {
t := data[0].(*toto)
t.name = "tutu"
}
func main() {
var titi toto
transform(&titi)
println(titi.name == "tutu")
}
Sounds like you want a pointer.
In your example you use an array of interface{}, is there a particular reason for this? In general you should be explicit with your types in Go, especially since you're dealing with a simple struct.
package main
import (
"log"
)
type toto struct {
Name string
}
// to help with printing
func (t *toto) String() string {
return t.Name
}
// transform takes an array of pointers to the toto struct
func transform(totos ...*toto) {
log.Printf("totos before: %v", totos)
// unsafe array access!
totos[0].Name = "tutu"
log.Printf("totos after: %v", totos)
}
func main() {
// variables in Go are usually defined like this
titi := toto{}
transform(&titi)
}
In Go, the variable that's passed as a parameter in a function is actually a copy of the variable, not the actual variable itself. If you want to modify the variable that's passed, you need to pass it in as a pointer.
Personally, whenever I create a function that accepts a struct, I set the function to accept a pointer to an instance of that struct. This has the benefits of being more memory efficient (since my program doesn't have to create copies of the variable every time the function is called) and it allows me to modify the instance of the struct that I pass.
This is how I would do it:
package main
import (
"github.com/sirupsen/logrus"
)
type toto struct {
name string
}
func transform (t *toto) {
logrus.Info("t before: ", t)
// since t is a pointer to a toto struct,
// I can directly assign "tutu" to the "name" field
// using the "dot" operator
t.name = "tutu"
logrus.Info("t after: ", t)
}
func main() {
// init a pointer to a toto instance
titi := &toto{}
logrus.Info("titi before: ", titi) // -> empty
// this works because transform() accepts a pointer
// to a toto struct and and titi is a pointer to a toto instance
transform(titi)
logrus.Info("titi after (as a pointer): ", titi) // -> not empty
logrus.Info("titi after (as a value): ", *titi) // -> also not empty
}

How to call only specific functions that have an annotation or tag

Is there a way to add a tag or annotate some methods so that whenever an event arises all the methods with this tag or annotation get invoked?
How to achieve this in Go?
As others have said, no there are no annotations or tags on functions in Go.
However, it is more than possible to use a map (or slice) and a register function to keep records of other funcs (or interfaces). You just need to manually call that register func (usually in init() of that package).
For example,
package events
var eventFuncs = make(map[string]func())
func Register(event string, f func()) {
eventFuncs[event] = append(eventFuncs[event],f)
}
func Get(event string) []func() {
return eventFuncs[event]
}
And using the package to register:
package xy
import (
"fmt"
"some.url/events"
)
func Call() {
fmt.Println("Ha!")
}
func init() {
events.Register("x",Call)
}
And then call the funcs elsewhere:
package main
import (
"some.url/events"
)
func main() {
for _,f := range pkg.GetEvent("x") { f() }
}

Go variable initilization syntax

I notice two styles of initializing a struct type variable in Go code examples but I don't understand when to use each.
Style 1:
package main
import (
"fmt"
)
type Msg struct {
value string
}
func NewMsg(value string) (Msg) {
return Msg{value}
}
func main() {
fmt.Println("Hello, playground")
var helloMsg Msg
helloMsg = NewMsg("oi")
fmt.Println("Hello, ", helloMsg.value)
}
Style 2:
package main
import (
"fmt"
)
type Msg struct {
value string
}
func NewMsg(value string) (Msg) {
return Msg{value}
}
func main() {
fmt.Println("Hello, playground")
var helloMsg Msg
{
helloMsg = NewMsg("oi")
}
fmt.Println("Hello, ", helloMsg.value)
}
The first style is a simples variable initilization but the second is more obscure to me. What the curly braces do? Why should I use the second form?
EDIT:
For more context on the question, it arrised from this sample code of the Go Kit library: https://github.com/go-kit/kit/blob/master/examples/profilesvc/cmd/profilesvc/main.go
What the curly braces do?
They denote a code block. You use code blocks when you want to restrict scope of an identifier (to that block). Here it doesn't make sense, indeed, because you only have one identifier and it's from the outer scope.
Some reading:
Scopes in Go
Blocks in Go
I don't see the difference between these two styles.
They're totally the same.
{} this defines scope codes, and some variables declared inside it can only be used inside that scope.
But if you declare helloMsg outside and do = inside the {} block. 'helloMsg' hasn't been scoped.
So, these two formatted style are totally the same.

Two function names after func keyword - what is it?

How to understand the last function?
Why do we use different function names after func declaration?
How to use those function? Using it like shown in the main function is wrong.
package main
import (
"fmt"
)
func main() {
fmt.Println(incrementer()) //error
}
func incrementer() func() int { //what is it?!
i := 0
return func() int {
i++
return i
}
}
It just means that the function is returning a function that takes no parameters and returns an integer. That is what the
... func() int
part of your signature is saying.
The error you are getting is because you fmt.Println cannot print a function. To show this you can see that you get the same error if you call,
func main() {
fmt.Println(foo)
}
func foo() int {
return 1
}
It might be clearer to see what is going on if you call your function like this.
func main() {
myIncrementer := incrementer()
fmt.Println(myIncrementer()) // Prints 1
}
Where you are creating incrementer, which is a function, then calling that function function which returns 1.
Simply, since incrementer() returns a function, the function that it returns must be called as well. You can do so like this:
functionFoo := incrementer()
fmt.Println(functionFoo())
Or this shorthanded way:
fmt.Println(incrementer()())
Which achieves the same thing, you just immediately execute the function that incrementer() returns.

How do I pass a pointer to a structure in a function?

I wonder how to replace *Type by ? What address has the structure inside?
//mycode.go
package main
import "fmt"
func out(k *Type) {
fmt.Println(k)
}
func main() {
type DataIP struct{ Title, Desc string }
Data := DataIP{
"Hello!",
"Hello GO!",
}
out(&Data)
}
You need to define the type DataIP outside of main() that the type is in the scope of the package and not just inside of the main function:
package main
import "fmt"
type DataIP struct{ Title, Desc string }
func out(k *DataIP) {
fmt.Println(k)
}
func main() {
Data := DataIP{
"Hello!",
"Hello GO!",
}
out(&Data)
}
https://play.golang.org/p/cUS6ttcUy-
I am not sure to understand your question.
If you want out to work only with structs of type DataIP:
simply define DataIP outside of main and use the signature func out(k *DataIP).
if what you want is to be able to pass any type of structure to out:
In golang, this sort of generic methods can be implemented using the interface type. As this answer explains, an interface is a container with two words of data:
one word is used to point to a method table for the value’s underlying type,
and the other word is used to point to the actual data being held by that value.
An interface can hold anything and is often used as a function parameter to be able to process many sort of inputs.
In your case, you can do:
func out(k interface{}) {
fmt.Println(k)
}
This will print &{Hello! Hello GO!}. In case you want the & to disappear (i.e. you always pass it pointers), you can use the reflect package to "dereference" k:
func out(k interface{}) {
fmt.Println(reflect.ValueOf(k).Elem())
}
which yields {Hello! Hello GO!}
Here is a playground example.
if what you want is to print the address of Data:
you can use the %p pattern with fmt.Printf:
fmt.Printf("%p", &Data) // 0x1040a130
Using the out function, you get:
func out(k interface{}) {
fmt.Printf("%p\n", k)
}
See this playground example

Resources