-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
108 lines (94 loc) · 3.86 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package main
import (
"database/sql"
"flag"
"html/template"
"log"
"net/http"
"os"
"github.com/andreagrandi/snippetbox/pkg/models/mysql"
_ "github.com/go-sql-driver/mysql" // New import
)
// Define an application struct to hold the application-wide dependencies for the
// web application. For now we'll only include fields for the two custom loggers, but
// we'll add more to it as the build progresses.
type application struct {
errorLog *log.Logger
infoLog *log.Logger
snippets *mysql.SnippetModel
templateCache map[string]*template.Template
}
func main() {
// Define a new command-line flag with the name 'addr', a default value of ":4000"
// and some short help text explaining what the flag controls. The value of the
// flag will be stored in the addr variable at runtime.
addr := flag.String("addr", ":4000", "HTTP network address")
// Define a new command-line flag for the MySQL DSN string.
dsn := flag.String("dsn", "root:my-secret-pw@/snippetbox?parseTime=true", "MySQL data source name")
// Importantly, we use the flag.Parse() function to parse the command-line flag.
// This reads in the command-line flag value and assigns it to the addr
// variable. You need to call this *before* you use the addr variable
// otherwise it will always contain the default value of ":4000". If any errors are
// encountered during parsing the application will be terminated.
flag.Parse()
// Use log.New() to create a logger for writing information messages. This takes
// three parameters: the destination to write the logs to (os.Stdout), a string
// prefix for message (INFO followed by a tab), and flags to indicate what
// additional information to include (local date and time). Note that the flags
// are joined using the bitwise OR operator |.
infoLog := log.New(os.Stdout, "INFO\t", log.Ldate|log.Ltime)
// Create a logger for writing error messages in the same way, but use stderr as
// the destination and use the log.Lshortfile flag to include the relevant
// file name and line number.
errorLog := log.New(os.Stderr, "ERROR\t", log.Ldate|log.Ltime|log.Lshortfile)
// To keep the main() function tidy I've put the code for creating a connection
// pool into the separate openDB() function below. We pass openDB() the DSN
// from the command-line flag.
db, err := openDB(*dsn)
if err != nil {
errorLog.Fatal(err)
}
// We also defer a call to db.Close(), so that the connection pool is closed
// before the main() function exits.
defer db.Close()
// Initialize a new template cache...
templateCache, err := newTemplateCache("./ui/html/")
if err != nil {
errorLog.Fatal(err)
}
// Initialize a new instance of application containing the dependencies.
app := &application{
errorLog: errorLog,
infoLog: infoLog,
snippets: &mysql.SnippetModel{DB: db},
templateCache: templateCache,
}
// Initialize a new http.Server struct. We set the Addr and Handler fields so
// that the server uses the same network address and routes as before, and set
// the ErrorLog field so that the server now uses the custom errorLog logger in
// the event of any problems.
srv := &http.Server{
Addr: *addr,
ErrorLog: errorLog,
Handler: app.routes(),
}
// The value returned from the flag.String() function is a pointer to the flag
// value, not the value itself. So we need to dereference the pointer (i.e.
// prefix it with the * symbol) before using it. Note that we're using the
// log.Printf() function to interpolate the address with the log message.
infoLog.Printf("Starting server on %s", *addr)
err = srv.ListenAndServe()
errorLog.Fatal(err)
}
// The openDB() function wraps sql.Open() and returns a sql.DB connection pool
// for a given DSN.
func openDB(dsn string) (*sql.DB, error) {
db, err := sql.Open("mysql", dsn)
if err != nil {
return nil, err
}
if err = db.Ping(); err != nil {
return nil, err
}
return db, nil
}