global var available in different files (same package)

1,122 views
Skip to first unread message

Natxo Asenjo

unread,
Jun 6, 2019, 3:07:22 PM6/6/19
to golang-nuts
hi,

I'd like to define a couple of global variables in a small cli app. The app has a few files but it's not large.

What I'd like is to use cli flags to define options, and those options should be available for all the functions. I quite like the fact that the content of the variables is checked for correctnes.

Code (using kingpin):

==============kinpingtest.go=====================================
package main

import (
    "gopkg.in/alecthomas/kingpin.v2"
    "os"
)

var (
    app    = kingpin.New("shittytest", "shitty kingpin test")
    url    = app.Flag("url", "url for app").Required().Short('u').URL()
    domain = app.Flag("domain", "domain for app").Short('d').Required().String()
)

func main() {
    kingpin.MustParse(app.Parse(os.Args[1:]))
   
    whatever()
}

================end kingpintest.go================================
and second file:

=================otherfile.go====================================
package main

import (
    "fmt"
)

func whatever() {
    u := *url
    fmt.Println(u.String() + "/that")
    fmt.Println(*domain)
}

===================endotherfile.go===================================

And quit unsurprisingly, running it:

$ go run *.go --url http://this.com --domain kk.kk
http://this.com/that
kk.kk

The 'problem' I have is that I cannot use the variables directly and have to convert them to strings first, and as far as I can see I cannot do that globally because the kingpin arguments get parsed in main().

I see one possible solution, and that is to convert the vars to strings in main() and pass those as arguments to funcs called from main().

Are there better options for what I want to achieve (certainly must be, I am just a go newbie)?

Thanks in advance.

Regards,
Natxo

jake...@gmail.com

unread,
Jun 7, 2019, 12:07:09 PM6/7/19
to golang-nuts
It is unclear  what the problem is. Global variables will be accessible from any file that is part of package "main". As you said, you could convert the strings in main(), then put them in some global variables, for use by you other functions. That way you wold not have to be passing them around. Or am I missing something?

Of course, the use of globals raises style issues, but that is a different discussion.

Natxo Asenjo

unread,
Jun 7, 2019, 2:12:22 PM6/7/19
to golang-nuts


On Friday, June 7, 2019 at 6:07:09 PM UTC+2, jake...@gmail.com wrote:


It is unclear  what the problem is. Global variables will be accessible from any file that is part of package "main". As you said, you could convert the strings in main(), then put them in some global variables, for use by you other functions. That way you wold not have to be passing them around. Or am I missing something?

yes, I understand it's unclear, if you do not fully understand something it's difficult to put it into words.

What I mean is that if I convert the var url URL to a string type variable (in this case I need to pass the uri around I get from the cli flag), and this conversion takes places forcefully after parsing the cli args, in func main(), then the new string variable is not passed to the second file. I need to pass it as an argument to the function I want to execute in the second file.

so first file:

func main() {                                                                  
    kingpin.MustParse(app.Parse(os.Args[1:]))                                  
    uri := *url                                                                
    fmt.Println(uri.String(), "from main.go")                                  
                                                                               
    whatever()                                                                 
}

second file:

func whatever() {   
                    
    fmt.Println(uri.String(), "from ww.go")                               
}

$ go run *.go -u kk
# command-line-arguments
./ww.go:10:14: undefined: uri

But the url var is available, I just need to unpack it everytime, which is tedious.

I hope I made it clearer now. It's not really an issue but a question to find a better way if possible ;-)

Thanks,

regards,
Natxo

jake...@gmail.com

unread,
Jun 7, 2019, 6:54:55 PM6/7/19
to golang-nuts
If I understand correctly, you should just be able to convert once, in main(), and store it in a global. Something like (code untested):
==============kinpingtest.go=====================================
package main

import (
   
"gopkg.in/alecthomas/kingpin.v2"
   
"os"
)

var (
    app    
= kingpin.New("shittytest", "shitty kingpin test")
    url    
= app.Flag("url", "url for app").Required().Short('u').URL()
    domain
= app.Flag("domain", "domain for app").Short('d').Required().String()

    realURL
string
)


func main
() {
    kingpin
.MustParse(app.Parse(os.Args[1:]))

    realURL
= *url.String()
   
    whatever
()

}

================end kingpintest.go================================
and second file:

=================otherfile.go====================================
package main

import (
   
"fmt"
)

func whatever
() {

    fmt
.Println(realURL + "/that")
    fmt
.Println(*domain)
}

===================endotherfile.go===================================

Note that whatever() simply acccesses the global variable realURL that you set in main().  I think that does what you want.
 
Reply all
Reply to author
Forward
0 new messages