Basic web application
Make a folder in your $GOPATH/src/github.com/<yourname>/Tasks
substitute your username in lieu of <yourname>
.
Create a file main.go
file main.go
package main
import (
"log"
"net/http"
)
func main() {
PORT := "127.0.0.1:8080"
log.Fatal(http.ListenAndServe(PORT, nil))
}
We import the http package in our application with import net/http
.
Now go to your terminal and type
[Tasks] $ go run main.go
You will notice that the program doesn't print anything because we told it only to listen on the port. If we want to user to know that we are running a server on that port, we should print a message saying so, as shown in the below example.
code example file: 3.1basicServer.go
package main
import (
"log"
"net/http"
)
func main() {
PORT := ":8080"
log.Print("Running server on "+ PORT)
log.Fatal(http.ListenAndServe(PORT, nil))
}
Whenever we run this, we'll get the below output
2016/01/01 22:00:36 Running server on :8080
Open localhost:8080
in a browser and you'll get the message "404 page not found"
We have just started a server to listen on the port 8080. We haven't handled the URL, i.e. we do not have a mechanism to respond to the GET / request which the browser is going to send when we hit the localhost:8080 URL.
Handling URLs
http.HandleFunc("/complete/", ShowCompleteTasksFunc)
//ShowCompleteTasksFunc is used to populate the "/completed/" URL
func ShowCompleteTasksFunc(w http.ResponseWriter, r *http.Request) {
}
We use HandleFunc in the net/http
package to handle URLs. The first argument is the URL to be handled and the second parameter is the function. We can define functions in the second parameter, but you are advised against it.
The handler function requires two arguments, a ResponseWriter object and a Request object. We are going to write to the ResponseWriter depending on what we get in the Request object. The ResponseWriter object is going to be the output, Request object is the input. The handler which we are writing is going to write data to the ResponseWriter object, which will be sent back to the user's browser.
Handler Example
We want to write the URL that the user is visiting on our webapp. The URL can be found in the request object, r.URL.Path
.
package main
import (
"log"
"net/http"
)
func main() {
PORT := ":8080"
log.Print("Running server on "+ PORT)
http.HandleFunc("/",CompleteTaskFunc)
log.Fatal(http.ListenAndServe(PORT, nil))
}
func CompleteTaskFunc(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(r.URL.Path))
}
Parameterized routing
When we get the URL /tasks/124, we want to get the task number 124, we do the following
//GetTaskFunc is used to get a task
func GetTaskFunc(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
id := r.URL.Path[len("/tasks/"):]
w.Write([]byte("Get the task "+id))
}
We take a sub string of the URL and remove the /tasks/
part to get the ID of the task.
This example makes use of the slicing concept. It is simple, if Path
is our string variable then Path[1:] is the substring which includes everything from the first character, index being zero.
Note: Parameterized routing
Ideally we should not be checking the URL path inside our view, we are supposed to use a router. For real projects, you should use a router. But before we start using third party libraries, it is better to learn the concepts, hence, we won't be using a router now.
Serving static files
http.Handle("/static/", http.FileServer(http.Dir("public")))
For serving static files, we use the FileServer
method of the http package. It takes a folder as an argument. Make sure you give only the public folder path in the argument.
Homework
- Read the documentation of
net/http
&log
and get to know of the methods/functions in the packages. - Find out how many alternatives are there to ListenAndServe.
- Write a handler to serve static files, if file is available on that path then it should serve the file, otherwise it must return an HTTP404 error.
- Write a command line application to share files/folder over HTTP, the syntax should be like this
./wshare -f file.pdf
file on link = 192.168.2.1:8080. An advanced version of this can be a dropbox clone, where we have a UI to share files. If you build this, do email me!
Footnotes
Learn how to read documentation, it saves a lot of time.