Skip to content

Commit 60bcf2d

Browse files
committed
Merge pull request qiniu#4 from pipul/master
go book
2 parents ce1ffad + 3ec491c commit 60bcf2d

11 files changed

+627
-0
lines changed

chapter5/hello.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package main
2+
3+
import (
4+
"io"
5+
"log"
6+
"net/http"
7+
)
8+
9+
func helloHandler(w http.ResponseWriter, r *http.Request) {
10+
io.WriteString(w, "Hello world!")
11+
}
12+
13+
func main() {
14+
http.HandleFunc("/hello", helloHandler)
15+
err := http.ListenAndServe(":8080", nil)
16+
if err != nil {
17+
log.Fatal("ListenAndServer:", err.Error())
18+
}
19+
}

chapter5/icmptest.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package main
2+
3+
import (
4+
"net"
5+
"os"
6+
"io"
7+
"bytes"
8+
"fmt"
9+
)
10+
11+
func main() {
12+
if len(os.Args) != 2 {
13+
fmt.Println("Usage: ", os.Args[0], "host")
14+
os.Exit(1)
15+
}
16+
service := os.Args[1]
17+
18+
conn, err := net.Dial("ip4:icmp", service)
19+
checkError(err)
20+
21+
var msg [512]byte
22+
msg[0] = 8 // echo
23+
msg[1] = 0 // code 0
24+
msg[2] = 0 // checksum, fix later
25+
msg[3] = 0 // checksum, fix later
26+
msg[4] = 0 // identifier[0]
27+
msg[5] = 13 //identifier[1]
28+
msg[6] = 0 // sequence[0]
29+
msg[7] = 37 // sequence[1]
30+
len := 8
31+
32+
check := checkSum(msg[0:len])
33+
msg[2] = byte(check >> 8)
34+
msg[3] = byte(check & 255)
35+
36+
_, err = conn.Write(msg[0:len])
37+
checkError(err)
38+
39+
_, err = conn.Read(msg[0:])
40+
checkError(err)
41+
42+
fmt.Println("Got response")
43+
if msg[5] == 13 {
44+
fmt.Println("Identifier matches")
45+
}
46+
if msg[7] == 37 {
47+
fmt.Println("Sequence matches")
48+
}
49+
50+
os.Exit(0)
51+
}
52+
53+
func checkSum(msg []byte) uint16 {
54+
sum := 0
55+
56+
// assume even for now
57+
for n := 1; n < len(msg)-1; n += 2 {
58+
sum += int(msg[n])*256 + int(msg[n+1])
59+
}
60+
sum = (sum >> 16) + (sum & 0xffff)
61+
sum += (sum >> 16)
62+
var answer uint16 = uint16(^sum)
63+
return answer
64+
}
65+
66+
func checkError(err error) {
67+
if err != nil {
68+
fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
69+
os.Exit(1)
70+
}
71+
}
72+
73+
func readFully(conn net.Conn) ([]byte, error) {
74+
defer conn.Close()
75+
76+
result := bytes.NewBuffer(nil)
77+
var buf [512]byte
78+
for {
79+
n, err := conn.Read(buf[0:])
80+
result.Write(buf[0:n])
81+
if err != nil {
82+
if err == io.EOF {
83+
break
84+
}
85+
return nil, err
86+
}
87+
}
88+
return result.Bytes(), nil
89+
}

chapter5/jsondemo.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package main
2+
import (
3+
"encoding/json"
4+
"log"
5+
"os"
6+
)
7+
8+
func main() {
9+
dec := json.NewDecoder(os.Stdin)
10+
enc := json.NewEncoder(os.Stdout)
11+
for {
12+
var v map[string]interface{}
13+
if err := dec.Decode(&v); err != nil {
14+
log.Println(err)
15+
return
16+
}
17+
for k := range v {
18+
if k != "Title" {
19+
v[k] = nil
20+
}
21+
}
22+
if err := enc.Encode(&v); err != nil {
23+
log.Println(err)
24+
}
25+
}
26+
}

chapter5/photoweb.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+
"io"
5+
"os"
6+
"syscall"
7+
"log"
8+
"path"
9+
"net/http"
10+
"io/ioutil"
11+
"html/template"
12+
"runtime/debug"
13+
)
14+
15+
const (
16+
ListDir = 0x0001
17+
UPLOAD_DIR = "./uploads"
18+
TEMPLATE_DIR = "./views"
19+
)
20+
21+
templates := make(map[string]*template.Template)
22+
23+
func init() {
24+
fileInfoArr, err := ioutil.ReadDir(TEMPLATE_DIR)
25+
check(err)
26+
var templateName, templatePath string
27+
28+
for _, fileInfo := range fileInfoArr {
29+
templateName = fileInfo.Name()
30+
if ext := path.Ext(templateName); ext != ".html" {
31+
continue
32+
}
33+
templatePath = TEMPLATE_DIR + "/" + templateName
34+
log.Println("Loading template:", templatePath)
35+
t := template.Must(template.ParseFiles(templatePath))
36+
templates[templateName] = t
37+
}
38+
}
39+
40+
func check(err error) {
41+
if err != nil {
42+
panic(err)
43+
}
44+
}
45+
46+
func renderHtml(w http.ResponseWriter, tplName string, locals map[string]interface{}) {
47+
if tpl, ok := templates[tplName]; ok {
48+
err := tpl.Execute(w, locals)
49+
check(err)
50+
} else {
51+
log.Println("Loading template: ", tplName, "not found!");
52+
}
53+
}
54+
55+
func isExists(path string) (bool, error) {
56+
_, err := os.Stat(path)
57+
if err == nil {
58+
return true, nil
59+
}
60+
if e, ok := err.(*os.PathError); ok && e.Err == syscall.ENOENT {
61+
return false, nil
62+
}
63+
return false, err
64+
}
65+
66+
func uploadHandler(w http.ResponseWriter, r *http.Request) {
67+
if r.Method == "GET" {
68+
renderHtml(w, "upload", nil);
69+
}
70+
if r.Method == "POST" {
71+
f, h, err := r.FormFile("image")
72+
check(err)
73+
filename := h.Filename
74+
defer f.Close()
75+
t, err := ioutil.TempFile(UPLOAD_DIR, filename)
76+
check(err)
77+
defer t.Close()
78+
_, err = io.Copy(t, f)
79+
check(err)
80+
http.Redirect(w, r, "/view?id="+filename, http.StatusFound)
81+
}
82+
}
83+
84+
func viewHandler(w http.ResponseWriter, r *http.Request) {
85+
imageId := r.FormValue("id")
86+
imagePath := UPLOAD_DIR + "/" + imageId
87+
exists, _ := isExists(imagePath)
88+
if !exists {
89+
http.NotFound(w, r)
90+
return
91+
}
92+
93+
w.Header().Set("Content-Type", "image")
94+
http.ServeFile(w, r, imagePath)
95+
}
96+
97+
func listHandler(w http.ResponseWriter, r *http.Request) {
98+
fileInfoArr, err := ioutil.ReadDir("./uploads")
99+
check(err)
100+
locals := make(map[string]interface{})
101+
images := []string{}
102+
for _, fileInfo := range fileInfoArr {
103+
images = append(images, fileInfo.Name())
104+
}
105+
locals["images"] = images
106+
renderHtml(w, "list", locals)
107+
}
108+
109+
func safeHandler(fn http.HandlerFunc) http.HandlerFunc {
110+
return func(w http.ResponseWriter, r *http.Request) {
111+
defer func() {
112+
if e, ok := recover().(error); ok {
113+
http.Error(w, e.Error(),
114+
http.StatusInternalServerError)
115+
// 或者输出自定义的 50x 错误页面
116+
// w.WriteHeader(http.StatusInternalServerError)
117+
// renderHtml(w, "error", e)
118+
// logging
119+
log.Println("WARN: panic in %v. - %v", fn, e)
120+
log.Println(string(debug.Stack()))
121+
}
122+
}()
123+
fn(w, r)
124+
}
125+
}
126+
127+
func staticDirHandler(mux *http.ServeMux, prefix string, staticDir string, flags int) {
128+
mux.HandleFunc(prefix, func(w http.ResponseWriter, r *http.Request) {
129+
file := staticDir + r.URL.Path[len(prefix)-1:]
130+
if (flags & ListDir) == 0 {
131+
if exists, _ := isExists(file); !exists {
132+
http.NotFound(w, r)
133+
return
134+
}
135+
}
136+
http.ServeFile(w, r, file)
137+
})
138+
}
139+
140+
func main() {
141+
mux := http.NewServeMux()
142+
staticDirHandler(mux, "/assets/", "./public", 0)
143+
mux.HandleFunc("/", safeHandler(listHandler))
144+
mux.HandleFunc("/view", safeHandler(viewHandler))
145+
mux.HandleFunc("/upload", safeHandler(uploadHandler))
146+
err := http.ListenAndServe(":8080", mux)
147+
if err != nil {
148+
log.Fatal("ListenAndServe: ", err.Error())
149+
}
150+
}

chapter5/simplehttp.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package main
2+
3+
import (
4+
"net"
5+
"io"
6+
"os"
7+
"bytes"
8+
"fmt"
9+
)
10+
11+
func main() {
12+
if len(os.Args) != 2 {
13+
fmt.Fprintf(os.Stderr, "Usage: %s host:port", os.Args[0])
14+
os.Exit(1)
15+
}
16+
service := os.Args[1]
17+
18+
conn, err := net.Dial("tcp", service)
19+
checkError(err)
20+
21+
_, err = conn.Write([]byte("HEAD / HTTP/1.0\r\n\r\n"))
22+
checkError(err)
23+
24+
result, err := readFully(conn)
25+
checkError(err)
26+
27+
fmt.Println(string(result))
28+
29+
os.Exit(0)
30+
}
31+
32+
func checkError(err error) {
33+
if err != nil {
34+
fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
35+
os.Exit(1)
36+
}
37+
}
38+
39+
func readFully(conn net.Conn) ([]byte, error) {
40+
defer conn.Close()
41+
42+
result := bytes.NewBuffer(nil)
43+
var buf [512]byte
44+
for {
45+
n, err := conn.Read(buf[0:])
46+
result.Write(buf[0:n])
47+
if err != nil {
48+
if err == io.EOF {
49+
break
50+
}
51+
return nil, err
52+
}
53+
}
54+
return result.Bytes(), nil
55+
}

chapter5/simplehttp2.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package main
2+
3+
import (
4+
"net"
5+
"os"
6+
"fmt"
7+
"io/ioutil"
8+
)
9+
10+
func main() {
11+
if len(os.Args) != 2 {
12+
fmt.Fprintf(os.Stderr, "Usage: %s host:port ", os.Args[0])
13+
os.Exit(1)
14+
}
15+
service := os.Args[1]
16+
17+
tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
18+
checkError(err)
19+
20+
conn, err := net.DialTCP("tcp", nil, tcpAddr)
21+
checkError(err)
22+
23+
_, err = conn.Write([]byte("HEAD / HTTP/1.0\r\n\r\n"))
24+
checkError(err)
25+
26+
//result, err := readFully(conn)
27+
result, err := ioutil.ReadAll(conn)
28+
checkError(err)
29+
30+
fmt.Println(string(result))
31+
32+
os.Exit(0)
33+
}
34+
35+
func checkError(err error) {
36+
if err != nil {
37+
fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
38+
os.Exit(1)
39+
}
40+
}

0 commit comments

Comments
 (0)