Skip to content

Commit d18631b

Browse files
authored
Merge pull request #336 from tebeka/tebeka-flags
Fun With Flags
2 parents f756cee + 5236bbe commit d18631b

File tree

5 files changed

+590
-0
lines changed

5 files changed

+590
-0
lines changed

content/advent-2019/flag/app.go

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"log"
7+
"net/http"
8+
"os"
9+
"strconv"
10+
)
11+
12+
var config struct {
13+
port int
14+
host string
15+
}
16+
17+
const (
18+
httpdUsage = `usage: %s httpd
19+
Run HTTP server
20+
21+
Options:
22+
`
23+
checkUsage = "usage: %s check URL\n"
24+
)
25+
26+
func main() {
27+
flag.Usage = func() { // [1]
28+
fmt.Fprintf(flag.CommandLine.Output(), "usage: %s check|run\n", os.Args[0])
29+
flag.PrintDefaults()
30+
}
31+
flag.Parse()
32+
33+
if len(os.Args) < 2 { // [2]
34+
log.Fatalf("error: wrong number of arguments")
35+
}
36+
37+
var err error
38+
switch os.Args[1] { // [3]
39+
case "run":
40+
err = runHTTPD()
41+
case "check":
42+
err = checkHTTPD()
43+
default:
44+
err = fmt.Errorf("error: unknown command - %s", os.Args[1])
45+
}
46+
47+
if err != nil {
48+
log.Fatalf("error: %s", err)
49+
}
50+
51+
}
52+
53+
func checkHTTPD() error {
54+
fs := flag.NewFlagSet("check", flag.ContinueOnError) // [4]
55+
fs.Usage = func() {
56+
fmt.Fprintf(flag.CommandLine.Output(), checkUsage, os.Args[0])
57+
fs.PrintDefaults()
58+
}
59+
60+
if err := fs.Parse(os.Args[2:]); err != nil { // [5]
61+
return err
62+
}
63+
64+
if fs.NArg() != 1 {
65+
return fmt.Errorf("error: wrong number of arguments")
66+
}
67+
68+
url := fs.Arg(0) // [6]
69+
resp, err := http.Get(url)
70+
switch {
71+
case err != nil:
72+
return err
73+
case resp.StatusCode != http.StatusOK:
74+
return fmt.Errorf("error: bad status - %s", resp.Status)
75+
}
76+
77+
return nil
78+
}
79+
80+
func runHTTPD() error {
81+
fs := flag.NewFlagSet("check", flag.ContinueOnError)
82+
fs.Var(PortVar(&config.port), "port", "port to listen on")
83+
fs.StringVar(&config.host, "host", config.host, "host to listen on")
84+
fs.Usage = func() {
85+
fmt.Fprintf(flag.CommandLine.Output(), httpdUsage, os.Args[0])
86+
fs.PrintDefaults()
87+
}
88+
89+
if err := fs.Parse(os.Args[2:]); err != nil {
90+
return err
91+
}
92+
93+
http.HandleFunc("/", handler)
94+
addr := fmt.Sprintf("%s:%d", config.host, config.port)
95+
fmt.Printf("server ready on %s\n", addr)
96+
return http.ListenAndServe(addr, nil)
97+
}
98+
99+
func PortVar(port *int) *portVar {
100+
return &portVar{port}
101+
}
102+
103+
type portVar struct {
104+
port *int
105+
}
106+
107+
func (p *portVar) String() string {
108+
if p.port == nil {
109+
return ""
110+
}
111+
112+
return fmt.Sprintf("%d", *p.port)
113+
}
114+
115+
func (p *portVar) Set(s string) error {
116+
val, err := strconv.Atoi(s)
117+
if err != nil {
118+
return err
119+
}
120+
121+
const minPort, maxPort = 1, 65535
122+
if val < minPort || val > maxPort {
123+
return fmt.Errorf("port %d out of range [%d:%d]", val, minPort, maxPort)
124+
}
125+
126+
*p.port = val
127+
return nil
128+
}
129+
130+
func init() {
131+
// Set defaults
132+
s := os.Getenv("HTTPD_PORT")
133+
p, err := strconv.Atoi(s)
134+
if err == nil {
135+
config.port = p
136+
} else {
137+
config.port = 8080
138+
}
139+
140+
h := os.Getenv("HTTPD_HOST")
141+
if len(h) > 0 {
142+
config.host = h
143+
} else {
144+
config.host = "localhost"
145+
}
146+
}
147+
148+
func handler(w http.ResponseWriter, r *http.Request) {
149+
fmt.Fprintf(w, "Hello Gophers\n")
150+
}

content/advent-2019/flag/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module main
2+
3+
go 1.13
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"log"
7+
"net/http"
8+
"os"
9+
"strconv"
10+
)
11+
12+
var config struct {
13+
port int
14+
host string
15+
}
16+
17+
const (
18+
usage = `usage: %s
19+
Run HTTP server
20+
21+
Options:
22+
`
23+
)
24+
25+
func main() {
26+
flag.Var(PortVar(&config.port), "port", "port to listen on")
27+
flag.StringVar(&config.host, "host", config.host, "host to listen on")
28+
flag.Usage = func() {
29+
fmt.Fprintf(flag.CommandLine.Output(), usage, os.Args[0])
30+
flag.PrintDefaults()
31+
}
32+
flag.Parse()
33+
34+
http.HandleFunc("/", handler)
35+
addr := fmt.Sprintf("%s:%d", config.host, config.port)
36+
fmt.Printf("server ready on %s\n", addr)
37+
if err := http.ListenAndServe(addr, nil); err != nil {
38+
log.Fatalf("error: %s", err)
39+
}
40+
}
41+
42+
func PortVar(port *int) *portVar {
43+
return &portVar{port}
44+
}
45+
46+
type portVar struct {
47+
port *int
48+
}
49+
50+
func (p *portVar) String() string {
51+
if p.port == nil {
52+
return ""
53+
}
54+
55+
return fmt.Sprintf("%d", *p.port)
56+
}
57+
58+
func (p *portVar) Set(s string) error {
59+
val, err := strconv.Atoi(s)
60+
if err != nil {
61+
return err
62+
}
63+
64+
const minPort, maxPort = 1, 65535
65+
if val < minPort || val > maxPort {
66+
return fmt.Errorf("port %d out of range [%d:%d]", val, minPort, maxPort)
67+
}
68+
69+
*p.port = val
70+
return nil
71+
}
72+
73+
func init() {
74+
// Set defaults
75+
s := os.Getenv("HTTPD_PORT")
76+
p, err := strconv.Atoi(s)
77+
if err == nil {
78+
config.port = p
79+
} else {
80+
config.port = 8080
81+
}
82+
83+
h := os.Getenv("HTTPD_HOST")
84+
if len(h) > 0 {
85+
config.host = h
86+
} else {
87+
config.host = "localhost"
88+
}
89+
}
90+
91+
func handler(w http.ResponseWriter, r *http.Request) {
92+
fmt.Fprintf(w, "Hello Gophers\n")
93+
}

content/advent-2019/flag/httpd.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"log"
7+
"net/http"
8+
"os"
9+
"strconv"
10+
)
11+
12+
var config struct { // [1]
13+
port int
14+
host string
15+
}
16+
17+
const (
18+
usage = `usage: %s
19+
Run HTTP server
20+
21+
Options:
22+
`
23+
)
24+
25+
func main() {
26+
flag.IntVar(&config.port, "port", config.port, "port to listen on") // [2]
27+
flag.StringVar(&config.host, "host", config.host, "host to listen on") // [3]
28+
flag.Usage = func() { // [4]
29+
fmt.Fprintf(flag.CommandLine.Output(), usage, os.Args[0])
30+
flag.PrintDefaults()
31+
}
32+
flag.Parse() // [5]
33+
34+
http.HandleFunc("/", handler)
35+
addr := fmt.Sprintf("%s:%d", config.host, config.port)
36+
fmt.Printf("server ready on %s\n", addr)
37+
if err := http.ListenAndServe(addr, nil); err != nil {
38+
log.Fatalf("error: %s", err)
39+
}
40+
41+
}
42+
43+
func init() { // [6]
44+
// Set defaults
45+
s := os.Getenv("HTTPD_PORT")
46+
p, err := strconv.Atoi(s)
47+
if err == nil {
48+
config.port = p
49+
} else {
50+
config.port = 8080
51+
}
52+
53+
h := os.Getenv("HTTPD_HOST")
54+
if len(h) > 0 {
55+
config.host = h
56+
} else {
57+
config.host = "localhost"
58+
}
59+
}
60+
61+
func handler(w http.ResponseWriter, r *http.Request) {
62+
fmt.Fprintf(w, "Hello Gophers\n")
63+
}

0 commit comments

Comments
 (0)