-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 54debd8
Showing
15 changed files
with
2,707 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
# Lab 0: Go tutorial | ||
|
||
In this tutorial, we will briefly go over the most important concepts of the Go programming language. You will create a dashboard application visualizing data of the Massachusetts Bay Transportation Authority (MBTA). The main goal of the lab and the linked tutorials is to have you play around with Go --- familiarizing yourself with the covered concepts will come in handy for future labs! :) | ||
|
||
## Installation | ||
|
||
1. Follow [these instructions](https://go.dev/doc/install) to install Go. | ||
|
||
2. We recommend using VisualStudio Code to work on the labs. VisualStudio Code can be downloaded [from here](https://code.visualstudio.com/download). After installation, make sure to add Go extensions and tools: Open VS Code, open the extension manager by pressing `Ctrl + Shift + x`, type "go" into the search bar and hit enter, find the Go extension by the GO team at Google and install it, open the command palette by pressing `Ctrl + Shift + p`, run `Go: Install/Update Tools`, select all tools and click ok. | ||
|
||
3. Clone this github repository: In a directory of your choice, run `git clone https://github.com/MIT-DB-Class/lab0`. | ||
|
||
4. [Download the database file](https://www.dropbox.com/s/37k6lrqd9uq52aa/mbta.sqlite?dl=1) `mbta.sqlite` and place it in the `lab0` directory (where `main.go` is). | ||
|
||
5. You should be all set! You can run the code by typing `go run main.go` in your terminal from the `lab0` directory or clicking on "Run and Debug" in VS Code (on the very left, click on the icon with the bug and the triangle and then on "Run and Debug"). | ||
|
||
## Lab and Go walk through | ||
|
||
In the following, we walk you through the lab and want to point your attention towards some Go features. After the installation, the structure of your project should look as follows: | ||
|
||
``` | ||
. | ||
├─ handlers/ | ||
| ├─ handlers_test.go | ||
│ ├─ handlers.go | ||
| └─ template.html | ||
├─ ridership_db/ | ||
| ├─ csv_ridership_db.go | ||
│ ├─ interface_ridership_db.go | ||
| ├─ ridership_db_test.go | ||
| └─ sqlite_ridership_db.go | ||
├─ utils/ | ||
│ └─ render_chart.go | ||
├─ main.go | ||
├─ mbta.csv | ||
├─ mbta.sqlite # TODO: download using link above | ||
├─ go.mod | ||
├─ go.sum | ||
└─ README.md | ||
``` | ||
|
||
### Hello world | ||
|
||
In this lab you will implement a simple http server that visualizes ridership data from Boston's MBTA metro system. Go provides many tutorials with small sample applications that are a great way to play around with features of the language. For example, [this tutorial](https://go.dev/tour/basics/1) gives an introduction on Go's basic syntax, from structuring your files to writing a "Hello world" program. | ||
|
||
Please use the linked tutorials and documentation to familiarize yourself with the Go language, which we will use for all labs in this course. The tutorials and documentation linked in this lab should allow you to fill out the missing functions required for the web app. | ||
|
||
Please look at [this documentation](https://pkg.go.dev/net/http#hdr-Servers) for an overview on how http servers are created in Go. | ||
|
||
|
||
### Error handling | ||
|
||
Open `ridership_db/sqlite_ridership_db.go`. In line 14, we connect to a Sqlite database. This may fail because of various reasons, for example if the database file `mbta.sqlite` is not present. Go has a built-in `error` type which is used for error handling, and many methods in Go will return an error in addition to their normal return value. This is unlike the use of exceptions for error handling in Python and Java. [This tutorial](https://go.dev/doc/tutorial/handle-errors) discusses error handling in Go in more detail. | ||
|
||
|
||
### Control flow | ||
You've seen `if` statements when handling errors. `ridership_db/sqlite_ridership_db.go` also implements a very simple iteration logic. In line 33, we run a query against sqlite which returns `rows`, a pointer to the result set. In lines 40-47, we use the `next` and `scan` methods of `rows` to iterate through the result set and add the returned rows to a slice ("a list"). Both slices and pointers are explained in the next subsection --- for now, focus on familiarizing yourself with Go's control flow syntax. | ||
|
||
Check out [this tutorial](https://go.dev/tour/flowcontrol/1) to make yourself familiar with control flow in Go. | ||
|
||
### Pointers, structs, slices and maps | ||
|
||
Now, go to `ridership_db/csv_ridership_db.go` and look at lines 10 to 15. You can see how we define the `CsvRidershipDB` struct (like we have previously defined the `SqliteRidershipDB` struct). | ||
|
||
Note that when defining the struct, the asterisks ("\*") in lines 12 and 13 declare that `csvFile` is a *pointer* to an `os.File` and `csvReader` is a *pointer* to a `csv.Reader`. These pointer variables are used to store the memory addresses where the actual `os.File` and `csv.Reader` reside in memory. | ||
The main use of pointers in Go is to "pass by reference" -- if a function takes a pointer argument and makes a change to the passed value, that value will also be seen by the caller (similarly if a function returns a pointer argument, the returned value may be changed by the caller). If the "\*" is omitted, this is "pass by value"; pass-by-value arguments to functions receive a copy of the value, and thus any changes made to them will be made on a copy and not seen by the caller. | ||
|
||
In line 11, you can see how we define a *map*, which is Go's analog to a Python dictionary or a C++ unordered_map. | ||
You will have to implement the `GetRidershipMethod` for `CsvRidershipDB`, which returns an int64 *slice* (`[]int64`) and an error. Slices are Go's analog to a Python list or a C++ vector. Note that slices and maps are always passed by reference in Go. | ||
|
||
Look at [this tutorial](https://go.dev/tour/moretypes/1) to make yourself familiar with pointers, structs, slices and maps. If you want additional material on pointers, have a look at [this tutorial](https://www.geeksforgeeks.org/pointers-in-golang/?ref=lbp). | ||
|
||
|
||
### Methods and interfaces | ||
|
||
Both the `SqliteRidershipDB` type and the `CsvRidershipDB` type implement the `RidershipDB` interface, which is defined in `ridership_db/interface_ridership_db.go`. A type implements an interface by implementing all of its methods. Note that this is usually implicit -- nowhere do we explicitly indicate that the two ridership types implement `RidershipDB`. Interfaces allow us to simply use the `RidershipDB` type in lines 23-24 in `handlers.go`, without needing to distinguish which of the two implementations we are using (`SqliteRidershipDB` or `CsvRidershipDB`). | ||
|
||
[This tutorial](https://go.dev/tour/methods/1) gives more detail on methods and interfaces. | ||
|
||
### It doesn't stop here | ||
|
||
The above resources provide a very brief overview of the most important features of the Go language. However, there are many more resources online as Go has a large and supportive community. We strongly encourage you to explore these resources and gain more experience with Go. If you find any tutorials particularly useful, please send them to us! :) 65830-staff [at] mit [dot] edu | ||
|
||
|
||
## The Assignment | ||
|
||
Complete the following two tasks for this lab: | ||
|
||
### 1. Start an http server and handle requests | ||
|
||
This task requires you to start up the http server in `main.go` and handle the user's GET requests by filling out the `HomeHandler` method in `handlers/handlers.go`. | ||
|
||
The final web app looks like in the screenshot below, where users can select a T line (e.g. red line) and display its ridership statistics in a bar chart. The `HomeHandler` function first checks which line the user has selected in the drop down menu and then queries ridership numbers for that line from a `RiderhipDB` instance. The returned values are then displayed in a bar chart. You don't need to write code to plot the bar chart yourself, you can simply use the `GenerateBarChart` function in `utils/render_chart.go`. | ||
|
||
After completing this task, you should be able to start the web server by running `go run main.go` and see the web app in your browser by going to http://localhost:PORT (where PORT is the port number you specified): | ||
|
||
![Screenshot of web app](screenshot.png) | ||
|
||
You should also be able to pass the test in `handlers_test.go`: When running `go test` from the `handlers` directory, you should get a similar output to this: | ||
|
||
``` | ||
PASS | ||
ok main/handlers 0.246s | ||
``` | ||
|
||
### 2. Run a query over a CSV file | ||
|
||
This task requires you to implement the missing methods in `ridership_db/csv_ridership_db.go` | ||
|
||
Instead of issuing the query against sqlite, `CsvRidershipDB` directly runs it over the `mbta.csv` CSV file. MBTA divides a day into nine different time periods (*time_period_01*, ..., *time_period_09*). The CSV file contains how many passengers boarded trains during a specific time period, at a specific station and for a specific line and direction. For the queried line (passed to `GetRidership`) compute the total number of passengers that boarded a train for each given time period (for each time period, sum over all stations and directions). The sum for each time period should be an entry in the returned `int64` slice. Make sure to use the `idIdxMap` map to map the time period id strings (e.g. *time_period_01*) to the correct index in the `boardings` slice (e.g. 0). | ||
|
||
To use your CSV implementation in the web app, instantiate RidershipDB to be a `CsvRidershipDB` instead of a `SqliteRidershipDB` in lines 23-24 in `handlers/handlers.go`: | ||
|
||
``` | ||
// instantiate ridershipDB | ||
// var db rdb.RidershipDB = &rdb.SqliteRidershipDB{} // Sqlite implementation | ||
var db rdb.RidershipDB = &rdb.CsvRidershipDB{} // CSV implementation | ||
``` | ||
|
||
You should also be able to pass the tests in `ridership_db/ridership_db_test.go`: When running `go test` from the `ridership_db` directory, you should get a similar output to this: | ||
|
||
``` | ||
=== RUN TestRidershipDBsMatch | ||
=== RUN TestRidershipDBsMatch/red | ||
--- PASS: TestRidershipDBsMatch/red (0.00s) | ||
=== RUN TestRidershipDBsMatch/green | ||
--- PASS: TestRidershipDBsMatch/green (0.00s) | ||
=== RUN TestRidershipDBsMatch/blue | ||
--- PASS: TestRidershipDBsMatch/blue (0.00s) | ||
=== RUN TestRidershipDBsMatch/orange | ||
--- PASS: TestRidershipDBsMatch/orange (0.00s) | ||
--- PASS: TestRidershipDBsMatch (0.01s) | ||
PASS | ||
ok main/ridership_db 0.226s | ||
``` | ||
|
||
## Submission | ||
|
||
50% of the grade is determined by an autograder, which checks if your code passes the test cases. The remaining 50% comes from us inspecting your code. | ||
|
||
To submit your code, please do the following: | ||
|
||
1. In the `lab0` directory, run `zip -r submission.zip handlers utils ridership_db main.go`. | ||
|
||
2. Submit the generated zip to [the autograder](https://www.gradescope.com/courses/583077/assignments/3263816/). | ||
|
||
3. The autograder should give you a score, based on whether your code passes the test cases. We will release the remaining 50% of the grade later. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
module main | ||
|
||
go 1.20 | ||
|
||
require ( | ||
github.com/gorilla/mux v1.8.0 | ||
github.com/mattn/go-sqlite3 v1.14.17 | ||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect | ||
github.com/wcharczuk/go-chart v2.0.1+incompatible // indirect | ||
golang.org/x/image v0.11.0 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= | ||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= | ||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= | ||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= | ||
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= | ||
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= | ||
github.com/wcharczuk/go-chart v2.0.1+incompatible h1:0pz39ZAycJFF7ju/1mepnk26RLVLBCWz1STcD3doU0A= | ||
github.com/wcharczuk/go-chart v2.0.1+incompatible/go.mod h1:PF5tmL4EIx/7Wf+hEkpCqYi5He4u90sw+0+6FhrryuE= | ||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= | ||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | ||
golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo= | ||
golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8= | ||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= | ||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= | ||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= | ||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= | ||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= | ||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= | ||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | ||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= | ||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= | ||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= | ||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= | ||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package handlers | ||
|
||
import ( | ||
"encoding/base64" | ||
"fmt" | ||
"html/template" | ||
rdb "main/ridership_db" | ||
"main/utils" | ||
"net/http" | ||
"os" | ||
"path/filepath" | ||
"runtime" | ||
) | ||
|
||
func HomeHandler(w http.ResponseWriter, r *http.Request) { | ||
// Get the selected chart from the query parameter | ||
selectedChart := r.URL.Query().Get("line") | ||
if selectedChart == "" { | ||
selectedChart = "red" | ||
} | ||
|
||
// instantiate ridershipDB | ||
var db rdb.RidershipDB = &rdb.SqliteRidershipDB{} // Sqlite implementation | ||
// var db rdb.RidershipDB = &rdb.CsvRidershipDB{} // CSV implementation | ||
|
||
// TODO: some code goes here | ||
// Get the chart data from RidershipDB | ||
|
||
// TODO: some code goes here | ||
// Plot the bar chart using utils.GenerateBarChart. The function will return the bar chart | ||
// as PNG byte slice. Convert the bytes to a base64 string, which is used to embed images in HTML. | ||
|
||
// Get path to the HTML template for our web app | ||
_, currentFilePath, _, _ := runtime.Caller(0) | ||
templateFile := filepath.Join(filepath.Dir(currentFilePath), "template.html") | ||
|
||
// Read and parse the HTML so we can use it as our web app template | ||
html, err := os.ReadFile(templateFile) | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
tmpl, err := template.New("line").Parse(string(html)) | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
// TODO: some code goes here | ||
// We now want to create a struct to hold the values we want to embed in the HTML | ||
data := struct { | ||
Image string | ||
Chart string | ||
}{ | ||
Image: "", // TODO: base64 string | ||
Chart: selectedChart, | ||
} | ||
|
||
// TODO: some code goes here | ||
// Use tmpl.Execute to generate the final HTML output and send it as a response | ||
// to the client's request. | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package handlers | ||
|
||
import ( | ||
"net/http" | ||
"net/http/httptest" | ||
"testing" | ||
) | ||
|
||
func TestHomeHandler(t *testing.T) { | ||
// Create a mock server | ||
srv := httptest.NewServer(http.HandlerFunc(HomeHandler)) | ||
defer srv.Close() | ||
|
||
// Create an HTTP client | ||
client := &http.Client{} | ||
|
||
// Send a request to the mock server | ||
resp, err := client.Get(srv.URL) | ||
if err != nil { | ||
t.Fatalf("Failed to send request: %s", err) | ||
} | ||
defer resp.Body.Close() | ||
|
||
// Check the response | ||
if resp.StatusCode != http.StatusOK { | ||
t.Errorf("Expected status %d; got %d", http.StatusOK, resp.StatusCode) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>Lab 0</title> | ||
<script> | ||
function updateChart() { | ||
var selectedChart = document.getElementById("chartSelect").value; | ||
window.location.href = "/?line=" + selectedChart; | ||
} | ||
</script> | ||
</head> | ||
<body> | ||
<form> | ||
<select id="chartSelect" onchange="updateChart()"> | ||
<option value="red" {{if eq .Chart "red"}}selected{{end}}>Red line</option> | ||
<option value="green" {{if eq .Chart "green"}}selected{{end}}>Green line</option> | ||
<option value="blue" {{if eq .Chart "blue"}}selected{{end}}>Blue line</option> | ||
<option value="orange" {{if eq .Chart "orange"}}selected{{end}}>Orange line</option> | ||
</select> | ||
</form> | ||
<img src="data:image/png;base64,{{.Image}}" alt="Bar Chart"> | ||
|
||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"main/handlers" | ||
"net/http" | ||
) | ||
|
||
func main() { | ||
// TODO: some code goes here | ||
// Fill out the HomeHandler function in handlers/handlers.go which handles the user's GET request. | ||
// Start an http server using http.ListenAndServe that handles requests using HomeHandler. | ||
} |
Oops, something went wrong.