This may sound stupid but how do I define a global variable in Go? const myglobalvariable = "Hi there!" doesn't really work...
I just want to get the command line argument and after this I want to print it. I do this using this code snippet:
package main
import (
"flag"
"fmt"
)
func main() {
gettext();
fmt.Println(text)
}
func gettext() {
flag.Parse()
text := flag.Args()
if len(text) < 1 {
fmt.Println("Please give me some text!")
}
}
The problem is that it just prints an empty line so I thought about declaring a global variable using const myglobalvariable = "Hi there!" but I just get the error cannot use flag.Args() (type []string) as type ideal string in assignment...
...I know this is a noob question so I hope you can help me...
I see at least two questions here, maybe three.
How do you declare a global variable?
How do you declare a global constant?
How do you parse command line options and arguments?
I hope the code below demonstrates this in a helpful way. The flag package was one of the first packages I had to cut my teeth on in Go. At the time it wasn't obvious, though the documentation is improving.
FYI, at the time of this writing I am using http://weekly.golang.org as a reference. The main site is far too out of date.
package main
import (
"flag"
"fmt"
"os"
)
//This is how you declare a global variable
var someOption bool
//This is how you declare a global constant
const usageMsg string = "goprog [-someoption] args\n"
func main() {
flag.BoolVar(&someOption, "someOption", false, "Run with someOption")
//Setting Usage will cause usage to be executed if options are provided
//that were never defined, e.g. "goprog -someOption -foo"
flag.Usage = usage
flag.Parse()
if someOption {
fmt.Printf("someOption was set\n")
}
//If there are other required command line arguments, that are not
//options, they will now be available to parse manually. flag does
//not do this part for you.
for _, v := range flag.Args() {
fmt.Printf("%+v\n", v)
}
//Calling this program as "./goprog -someOption dog cat goldfish"
//outputs
//someOption was set
//dog
//cat
//goldfish
}
func usage() {
fmt.Printf(usageMsg)
flag.PrintDefaults()
os.Exit(1)
}
The closest thing to a global variable in Go is a package variable. You define one like
var text string
Command line arguments though, are already sitting in a package variable, os.Args, waiting for you to access them. You don't even need the flag package.
package main
import (
"fmt"
"os"
)
func main() {
if len(os.Args) < 2 { // (program name is os.Arg[0])
fmt.Println("Please give me some text!")
} else {
fmt.Println(os.Args[1:]) // print all args
}
}
Why do you need a global variable? For example,
package main
import (
"flag"
"fmt"
)
func main() {
text := gettext()
fmt.Println(text)
}
func gettext() []string {
flag.Parse()
text := flag.Args()
if len(text) < 1 {
fmt.Println("Please give me some text!")
}
return text
}
See how gofmt, godoc, and others handle the same thing.
Related
I have following code:
package main
import (
"fmt"
)
func test(data interface{}) {
data = "123"
}
func main() {
t := "org"
test(&t)
fmt.Println(t)
e := 1
test(&e)
fmt.Println(e)
}
I tried to add pointer to *interface{} but it throws errors, how can I assign string "test" to t when I print it? right now t will be printed out as "org"
I am asking because I am not sure how I can use dynamic type here, for instance, josn.Unmarshal(data []byte, v interface{}) I used this function, and it can convert databyte to any type we want as long as we pass the reference.
I think you are expecting interface to be much more magic than it actually is.
Consider this variant of your program:
package main
import (
"fmt"
)
func test(p *string) {
s := "test"
p = &s
}
func main() {
t := "org"
test(&t)
fmt.Println(t)
}
Do you expect this to print test? If so, we have a bigger problem. :-) If not, why do you expect the version with p interface{} to change t when assigning directly to p?
If we change test to write through *p:
func test(p *string) {
*p = "test"
}
the program does print test, as you expected.
All that remains now is to handle the case when p is declared instead as data interface{}. As in bserdar's answer, you must first extract the underlying *string pointer from the interface object in data. You can then use that pointer to set main's variable t. You could do this with two steps:
func test(data interface{}) {
p := data.(*string)
*p = "test"
}
for instance, or you can do it all in one line.
You are setting the interface, not the underlying value. Instead you should do
func test(data interface{}){
*data.(*string) = "aaa"
}
That is, first get the underlying string pointer, then set the string pointed by it.
For the snippet below (runnable via the Go Playground),
package main
import (
"fmt"
"net/http"
"reflect"
"runtime"
)
type User struct{}
var u = &User{}
func (_ User) DummyHandler(w http.ResponseWriter, r *http.Request) {}
func funcName(i interface{}) {
p := reflect.ValueOf(i).Pointer()
n := runtime.FuncForPC(p).Name()
fmt.Println(n)
}
func main() {
funcName(u.DummyHandler)
}
The output is main.(User).DummyHandler-fm.
Why is there a -fm at the end of the function name?
Turns out u.DummyHandler is a method value and the compiler implements methods by creating a function closure and modifying the function name. To quote Ian here:
This seems to have become -fm on tip, by the way.
Your code is getting a method value. p.beHappy is the beHappy method
bound to the specific value of p. That is implemented by creating a
function closure, and the code for that closure needs a name. The
compiler happens to make that name by sticking fm on the end, but it
could be anything that won't conflict with any other function name.
There isn't any way to name that function in Go, so the name is
irrelevant for anything other than the debugger or, as you see,
FuncForPC.
It seems like a better way to get a method's name is to reference the method directly, like so:
func main() {
funcName((User).DummyHandler)
}
This will output main.User.DummyHandler.
I have an issue using this statement
m.Post(Model, binding.Form(Wish), func(wish Wish, r render.Render, db *mgo.Database) {
This worked fine if I use the struct define inside the prog like
m.Post(Model, binding.Form(Wish1{}) , func(wish Wish1, r render.Render, db *mgo.Database) {
but I need this to be an independent package.
I get "Wish is not a type" wish is the return of the binding function.
This worked with a primary Type struct. I am passing the strut as a interface{}
I am using GO with Martini.Classic() It is really complicated for me to change Martini or Binding package. Any suggestions.
This is the all code
package chlistpkg
import (
"github.com/codegangsta/martini"
"github.com/codegangsta/martini-contrib/binding"
"github.com/codegangsta/martini-contrib/render"
"labix.org/v2/mgo"
"time"
"fmt"
"html/template"
"reflect"
"adminStruct"
)
just to show the struct that I need to pass as to routine Doall
type Wish1 struct {
Name string `form:"name"`
Description string `form:"description"`
AnyDate time.Time `form:"anydate"`
Active bool `form:"active"`
Number int `form:"number"`
NumDec float32 `form:"numDec"`
}
DB Returns a martini.Handler
func DB() martini.Handler {
session, err := mgo.Dial("mongodb://localhost")
if err != nil {
panic(err)
}
return func(c martini.Context) {
s := session.Clone()
c.Map(s.DB("advent2"))
defer s.Close()
c.Next()
}
}
GetAll returns all Wishes in the database
func GetAll(db *mgo.Database, entList interface{}) interface{} {
db.C("wishes").Find(nil).All(entList)
fmt.Println("GettAll entList =", entList)
return entList
}
func Doall(Model string, Wish interface{}, Wish2 interface{}, Wishlist interface{} ) {
m := martini.Classic()
fmt.Println ("martini.Classic =", m)
m.Use(martini.Static("images")) // serve from the "images" directory as well
m.Use(render.Renderer(render.Options{
Directory: "templates",
Layout: "layout",
}))
m.Use(DB())
m.Get(Model, func(r render.Render, db *mgo.Database) {
r.HTML(200, "lista4", GetAll(db, Wishlist))
})
binding does not take a pointer. I have to pass the struct by reference on "Wish"
the issue is the return on "wish Wish" I got an error Wish is not a type
at compilation time
m.Post(Model, binding.Form(Wish), func(wish Wish, r render.Render, db *mgo.Database) {
fmt.Println("Input wish =", wish)
db.C("wishes").Insert(wish)
r.HTML(200, "lista4", GetAll(db, Wishlist))
})
m.Run()
Thanks in advance
Luis
The reason you are getting an error is that you have called your type Wish1 (with a numerical 1) but you are referring to the Wish type (which does not exist!) in your code.
Change your struct to be:
// Note: "Wish", not "Wish1"
type Wish struct {
Name string `form:"name"`
Description string `form:"description"`
AnyDate time.Time `form:"anydate"`
Active bool `form:"active"`
Number int `form:"number"`
NumDec float32 `form:"numDec"`
}
If you want to put your type into another package (tip: don't overdo the sub-packages), then it will need to become a pkgname.Wish as names are fully qualified.
Added
After a second look, you're also messing things up here:
func Doall(Model string, Wish interface{}, Wish2 interface{}, Wishlist interface{} ) {
m := martini.Classic()
fmt.Println ("martini.Classic =", m)
m.Use(martini.Static("images")) // serve from the "images" directory as well
Your parameter list needs to provide a name for each type; you can't pass Wish interface{} as a parameter as Wish is a type, not a variable name.
You should either:
func DoAll(model string, wish interface{}, wish2 interface{}, wishList interface{}) { ... }
Or, better still, stop using interface{} like this and write:
func DoAll(model string, wishList []Wish, wishes... Wish) { ... }
However, your DoAll function does not seem to be referenced elsewhere, and is creating its own Martini instance. I highly suggest thinking about why things are "split out" like this if you're just starting out. Keep it simple - e.g.
func main() {
m := martini.Classic()
m.Use(martini.Static("images"))
m.Use(DB())
m.Use(render.Renderer(render.Options{...}))
// No need for an anonymous function, which just adds clutter
m.Get("/wishes/all", GetAllWishes)
// Same goes for here
m.Post("/wishes/new", PostWish)
m.Run()
}
PS: I've fixed the formatting of your code, as it has a lot of unnecessary spacing before/after parenthesis. Make sure to use gofmt, which is included with the Go install and can be hooked into most popular editors.
Context
I'm making a web app that serves dynamically generated pdfs. These contain content from the internet, so every time it serves a pdf, it downloads a number of files to a new temporary folder.
The Problem
I end up with a large number of folders after I load the page once, so it seems that, for some reason, the handler is being called multiple times, which is an issue because I'm downloading multiple times more than I need to of not insubstantial files. I'd like to check at what stage of the process multiple requests are occurring.
The Question
Is there a way of working out how many times a function has been called, quite possibly using closures? (I haven't quite got closures into my mental model for programming yet; I don't completely understand them/how they're used).
This would preferably be something involving an int in the language rather than printing something at every stage and counting by hand - I'm looking for a more scalable solution than that (for later situations as well as this one).
Thanks!
Here are two ways you can count function calls, and one for method calls. There are plenty of other ways too, but just to get you started:
Using closure: (not what I would recommended)
package main
import(
"fmt"
"sync/atomic"
)
var Foo = func() (func() uint64) {
var called uint64
return func() uint64 {
atomic.AddUint64(&called, 1)
fmt.Println("Foo!")
return called
}
}()
func main() {
Foo()
c := Foo()
fmt.Printf("Foo() is called %d times\n", c)
}
Playground: http://play.golang.org/p/euKbamdI7h
Using global counter:
package main
import (
"fmt"
"sync/atomic"
)
var called uint64
func Foo() {
atomic.AddUint64(&called, 1)
fmt.Println("Foo!");
}
func main() {
Foo()
Foo()
fmt.Printf("Foo() is called %d times\n", called)
}
Playground: http://play.golang.org/p/3Ib29VCnoF
Counting method calls:
package main
import (
"fmt"
"sync/atomic"
)
type T struct {
Called uint64
}
func (t *T) Foo() {
atomic.AddUint64(&t.Called, 1)
fmt.Println("Foo!")
}
func main() {
var obj T
obj.Foo()
obj.Foo()
fmt.Printf("obj.Foo() is called %d times\n", obj.Called)
}
Playground: http://play.golang.org/p/59eOQdUQU1
Edit:
I just realized that the handler might not be in your own package. In such a case, you might want to write a wrapper:
var called uint64
func Foo() {
atomic.AddUint64(&called, 1)
importedPackage.Foo()
}
Edit 2:
Updated the examples to use atomic +1 operations.
Counting Calls
To answer the specific question you asked, here is one quick way to count handler executions:
func countCalls(h http.HandlerFunc) http.HandlerFunc {
var lock sync.Mutex
var count int
return func(w http.ResponseWriter, r *http.Request) {
lock.Lock()
count++
w.Header().Set("X-Call-Count", fmt.Sprintf("%d", count))
lock.Unlock()
h.ServeHTTP(w, r)
}
}
http.Handle("/foobar", countCalls(foobarHandler))
This will add a header that you can inspect with your favorite web developer tools; you could also just log it to standard output or something.
Logging Handlers
To expand upon the answers mentioned above, what you probably want to do to debug this and have in place for future use is to log details of each request.
package main
import (
"flag"
"log"
"net/http"
"os"
"github.com/gorilla/handlers"
)
var (
accessLogFile = flag.String("log", "/var/log/yourapp/access.log", "Access log file")
)
func main() {
accessLog, err := os.OpenFile(*accessLogFile, os.O_CREATE|os.O_WRITE|os.O_APPEND, 0644)
if err != nil {
log.Fatalf("Failed to open access log: %s", err)
}
wrap := func(f http.HandlerFunc) http.Handler {
return handlers.LoggingHandler(accessLog, http.HandlerFunc(foobarHandler))
}
http.Handle("/foobar", wrap(foobarHandler))
...
}
This uses LoggingHandler (or CombinedLoggingHandler) to write a standard Apache format log message that you can either inspect yourself or analyze with various tools.
An example of a log line would be
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
which tells you who made the request, when, what the method and URL was, how your server responded, and how long the response was. From this log, you should be able to see exactly what requests are being made, to determine not only how many times your handlers are being called, but exactly what is generating the requests and whether they're to another endpoint (like /favicon.ico).
I wrote a simple program using the Go Playground at golang.org.
The output is obviously:
second test
first test
Is there a way to edit the map value in place? I know I can't take the andress of a.Things[key]. So, is setting a.Things[key] = firstTest the only way to do it? Maybe with a function ChangeThing(key string, value string)?
You could do it by making the values of your map pointers to another struct.
http://play.golang.org/p/UouwDGuVpi
package main
import "fmt"
type A struct {
Things map[string]*str
}
type str struct {
s string
}
func (a A) ThingWithKey(key string) *str {
return a.Things[key]
}
func main() {
variable := A{}
variable.Things = make(map[string]*str)
variable.Things["first"] = &str{s:"first test"}
firstTest := variable.ThingWithKey("first")
firstTest.s = "second test"
fmt.Println(firstTest.s)
fmt.Println(variable.ThingWithKey("first").s)
}
You can use a pointer as the map value http://play.golang.org/p/BCsmhevGMX