Passing the JSON argument via the Command-line flag seems to be not typical, but we may need it in some cases. This post will show you how to implement it in Golang.
The package flag
provides an easy way to implement it. Let’s take a look at a simple example of using package flag
first:
package main
import (
"flag"
"fmt"
)
func main() {
var version string
// parse the value of the flag setVersion to variable version
flag.StringVar(&version, "setVersion", "1.0.0", "")
flag.Parse()
fmt.Println("version = ", version)
}
The output is
go run main.go -setVersion "2.0.0"
version = 2.0.0
What if we want to pass a struct variable via the Command-Line arguments, how can we do? For example, set a Profile?
type Profile struct {
Name string
Age uint
Verified bool
}
Let’s change the above code to see what will happen
package main
import (
"flag"
"fmt"
)
type Profile struct {
Name string
Age uint
Verified bool
}
func main() {
var version string
var profile Profile // new added
flag.StringVar(&version, "setVersion", "1.0.0", "")
flag.Var(&profile, "setProfile", "") // new added
flag.Parse()
fmt.Println("version = ", version)
fmt.Println("profile = ", profile) // new added
}
When we execute it, the output shows like below
go run main.go -setProfile "{\"Name\": \"oscar\", \"Age\": 18, \"Verified\": false}"
# command-line-arguments
.\main.go:28:11: cannot use &profile (type *Profile) as type flag.Value in argument to flag.Var:
*Profile does not implement flag.Value (missing Set method)
The error message *Profile does not implement flag.Value (missing Set method)
indicates that the struct Profile is not completed for function flag.Var
.
flag.Var allows us to implement a user-defined value. Its prototype is flag.Var(value Value, name string, usage string)
. We notice that the type of the first argument value
is Value which is an interface. The prototype is
type Value interface {
String() string
Set(string) error
}
So what we need to do next is to implement the methods String() string
and Set(string) error
for struct Profile
.
package main
import (
"encoding/json"
"flag"
"fmt"
)
type Profile struct {
Name string
Age uint
Verified bool
}
// new added
func (this *Profile) String() string {
b, _ := json.Marshal(*this)
return string(b)
}
// new added
func (this *Profile) Set(s string) error {
return json.Unmarshal([]byte(s), this)
}
func main() {
var version string
var profile Profile
flag.StringVar(&version, "setVersion", "1.0.0", "")
flag.Var(&profile, "setProfile", "")
flag.Parse()
fmt.Println("version = ", version)
fmt.Println("profile = ", profile)
}
The output is
go run main.go -setProfile "{\"Name\": \"oscar\", \"Age\": 18, \"Verified\": false}"
version = 1.0.0
profile = {oscar 18 false}
In a nutshell, with the function flag.Var
, we can freely parse any values of user-defined type, like array, map, and struct.
If this post helped you to solve a problem or provided you with new insights, please upvote it and share your experience in the comments below. Your comments can help others who may be facing similar challenges. Thank you!