├── .idea
├── .gitignore
├── go-web-zero.iml
├── modules.xml
└── vcs.xml
├── go.mod
├── go.sum
├── img.png
├── img_1.png
├── img_10.png
├── img_11.png
├── img_12.png
├── img_13.png
├── img_14.png
├── img_15.png
├── img_16.png
├── img_17.png
├── img_18.png
├── img_19.png
├── img_2.png
├── img_20.png
├── img_21.png
├── img_22.png
├── img_23.png
├── img_24.png
├── img_25.png
├── img_26.png
├── img_27.png
├── img_28.png
├── img_29.png
├── img_3.png
├── img_30.png
├── img_31.png
├── img_32.png
├── img_33.png
├── img_34.png
├── img_35.png
├── img_36.png
├── img_37.png
├── img_38.png
├── img_39.png
├── img_4.png
├── img_40.png
├── img_41.png
├── img_42.png
├── img_43.png
├── img_44.png
├── img_45.png
├── img_46.png
├── img_47.png
├── img_5.png
├── img_6.png
├── img_7.png
├── img_8.png
├── img_9.png
├── p1
└── main.go
├── p10
├── index.html
└── main.go
├── p12
├── main.go
└── tmpl.html
├── p13
├── main.go
├── t1.html
├── t2.html
└── tmpl.html
├── p14
└── templates
│ └── about.html
├── p18
└── main.go
├── p19
├── main.go
├── model.go
└── service.go
├── p2
└── main.go
├── p21
├── about.html
├── controller
│ ├── about.go
│ ├── contact.go
│ ├── controller.go
│ └── home.go
├── home.html
├── layout.html
└── main.go
├── p23
├── main.go
├── middleware
│ └── auth.go
├── test.html
└── test.http
├── p24
└── main.go
├── p3
└── main.go
├── p5
├── main.go
└── test.http
├── p6
├── img
│ ├── img.png
│ └── p6-1.png
└── main.go
├── p7
├── index.html
└── main.go
├── p8
├── index.html
├── main.go
└── testloadfile.txt
└── readme.md
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/go-web-zero.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module go-web-zero
2 |
3 | go 1.17
4 |
5 | require github.com/denisenkom/go-mssqldb v0.12.0
6 |
7 | require (
8 | github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
9 | github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 // indirect
10 | golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 // indirect
11 | )
12 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
2 | github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
3 | github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
4 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6 | github.com/denisenkom/go-mssqldb v0.12.0 h1:VtrkII767ttSPNRfFekePK3sctr+joXgO58stqQbtUA=
7 | github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU=
8 | github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
9 | github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
10 | github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
11 | github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 h1:+eHOFJl1BaXrQxKX+T06f78590z4qA2ZzBTqahsKSE4=
12 | github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8=
13 | github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
14 | github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
15 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
16 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
17 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
18 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
19 | golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
20 | golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
21 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
22 | golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
23 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
24 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
25 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
26 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
27 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
28 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
29 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
30 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
31 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
32 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
33 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
34 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
35 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
36 |
--------------------------------------------------------------------------------
/img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img.png
--------------------------------------------------------------------------------
/img_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_1.png
--------------------------------------------------------------------------------
/img_10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_10.png
--------------------------------------------------------------------------------
/img_11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_11.png
--------------------------------------------------------------------------------
/img_12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_12.png
--------------------------------------------------------------------------------
/img_13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_13.png
--------------------------------------------------------------------------------
/img_14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_14.png
--------------------------------------------------------------------------------
/img_15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_15.png
--------------------------------------------------------------------------------
/img_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_16.png
--------------------------------------------------------------------------------
/img_17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_17.png
--------------------------------------------------------------------------------
/img_18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_18.png
--------------------------------------------------------------------------------
/img_19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_19.png
--------------------------------------------------------------------------------
/img_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_2.png
--------------------------------------------------------------------------------
/img_20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_20.png
--------------------------------------------------------------------------------
/img_21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_21.png
--------------------------------------------------------------------------------
/img_22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_22.png
--------------------------------------------------------------------------------
/img_23.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_23.png
--------------------------------------------------------------------------------
/img_24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_24.png
--------------------------------------------------------------------------------
/img_25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_25.png
--------------------------------------------------------------------------------
/img_26.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_26.png
--------------------------------------------------------------------------------
/img_27.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_27.png
--------------------------------------------------------------------------------
/img_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_28.png
--------------------------------------------------------------------------------
/img_29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_29.png
--------------------------------------------------------------------------------
/img_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_3.png
--------------------------------------------------------------------------------
/img_30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_30.png
--------------------------------------------------------------------------------
/img_31.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_31.png
--------------------------------------------------------------------------------
/img_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_32.png
--------------------------------------------------------------------------------
/img_33.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_33.png
--------------------------------------------------------------------------------
/img_34.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_34.png
--------------------------------------------------------------------------------
/img_35.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_35.png
--------------------------------------------------------------------------------
/img_36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_36.png
--------------------------------------------------------------------------------
/img_37.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_37.png
--------------------------------------------------------------------------------
/img_38.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_38.png
--------------------------------------------------------------------------------
/img_39.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_39.png
--------------------------------------------------------------------------------
/img_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_4.png
--------------------------------------------------------------------------------
/img_40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_40.png
--------------------------------------------------------------------------------
/img_41.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_41.png
--------------------------------------------------------------------------------
/img_42.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_42.png
--------------------------------------------------------------------------------
/img_43.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_43.png
--------------------------------------------------------------------------------
/img_44.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_44.png
--------------------------------------------------------------------------------
/img_45.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_45.png
--------------------------------------------------------------------------------
/img_46.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_46.png
--------------------------------------------------------------------------------
/img_47.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_47.png
--------------------------------------------------------------------------------
/img_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_5.png
--------------------------------------------------------------------------------
/img_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_6.png
--------------------------------------------------------------------------------
/img_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_7.png
--------------------------------------------------------------------------------
/img_8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_8.png
--------------------------------------------------------------------------------
/img_9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/img_9.png
--------------------------------------------------------------------------------
/p1/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "net/http"
4 |
5 | func main() {
6 | // 调用适配器处理函数,两个参数,一个http地址,一个是hangler函数
7 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
8 | w.Write([]byte("hello go"))
9 | })
10 |
11 | //设置web 服务器,俩个参数,一个监听地址port,一个handler,默认是nil, 采用多路复用mux
12 | http.ListenAndServe("localhost:8080", nil)
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/p10/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Go web
6 |
7 |
8 | hello go go go world
9 |
10 |
--------------------------------------------------------------------------------
/p10/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "encoding/json"
5 | "net/http"
6 | )
7 |
8 | func writeExample(w http.ResponseWriter, r *http.Request) {
9 | str := `
10 |
11 |
12 |
13 | Go web
14 |
15 |
16 | hello go go go world
17 |
18 | `
19 |
20 | w.Write([]byte(str)) // 把str 写入到body 里面, 需要类型转换
21 | }
22 |
23 | func headerExample(w http.ResponseWriter, r *http.Request) {
24 | w.Header().Set("Location", "http://baidu.com")
25 | // 必须调用前修改header
26 | w.WriteHeader(302) // 重定向302
27 | }
28 |
29 | type POST struct {
30 | User string
31 | Thread []string
32 | }
33 |
34 | func jsonExample(w http.ResponseWriter, r *http.Request) {
35 | w.Header().Set("Content-Type", "application/json")
36 | post := &POST{
37 | User: "xxpkk",
38 | Thread: []string{"first", "second", "third"},
39 | }
40 | json, _ := json.Marshal(post)
41 | w.Write(json)
42 | }
43 |
44 | func main() {
45 |
46 | server := http.Server{
47 | Addr: "localhost:8080",
48 | }
49 | http.HandleFunc("/write", writeExample)
50 | http.HandleFunc("/redirect", headerExample)
51 |
52 | //json 案例
53 | http.HandleFunc("/json", jsonExample)
54 | server.ListenAndServe()
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/p12/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "html/template"
5 | "net/http"
6 | )
7 |
8 | // 自定义的handler
9 | func process(w http.ResponseWriter, r *http.Request) {
10 | // 解析模板文件,相对路径
11 | t, _ := template.ParseFiles("tmpl.html")
12 | // 执行模板,传入数据,替换{{.}}
13 | t.Execute(w, "hello go go go go")
14 | }
15 |
16 | func main() {
17 | server := http.Server{
18 | Addr: "localhost:8080",
19 | }
20 | http.HandleFunc("/test", process)
21 | server.ListenAndServe()
22 | }
23 |
--------------------------------------------------------------------------------
/p12/tmpl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | test template
6 |
7 |
8 | 下面是模板输出的内容:
9 | {{ . }}
10 |
11 |
--------------------------------------------------------------------------------
/p13/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "net/http"
5 | "text/template"
6 | )
7 |
8 | func main() {
9 |
10 | server := http.Server{
11 | Addr: "localhost:8080",
12 | }
13 | http.HandleFunc("/process", process)
14 | server.ListenAndServe()
15 |
16 | }
17 |
18 | func process(w http.ResponseWriter, r *http.Request) {
19 | //解析1个模板
20 | t, _ := template.ParseFiles("tmpl.html")
21 | t.Execute(w, "hello go")
22 | ////等价于下面两句话
23 | //t := template.New("tmpl.html")
24 | //t, _ = t.ParseFiles("tmpl.html")
25 |
26 | //t1,_, := template.ParseGlob("*.html")
27 |
28 | //解析多个模板
29 | ts, _ := template.ParseFiles("t1.html", "t2.html")
30 | ts.ExecuteTemplate(w, "t2.html", "hello go t2")
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/p13/t1.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | test template
6 |
7 |
8 | 下面是模板输出的内容:
9 | {{ . }}
10 |
11 |
--------------------------------------------------------------------------------
/p13/t2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | test template
6 |
7 |
8 | 下面是模板输出的内容:
9 | {{ . }}
10 |
11 |
--------------------------------------------------------------------------------
/p13/tmpl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | test template
6 |
7 |
8 | 下面是模板输出的内容:
9 | {{ . }}
10 |
11 |
--------------------------------------------------------------------------------
/p14/templates/about.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | about
6 |
7 |
8 |
9 | this is about
10 |
11 |
12 |
--------------------------------------------------------------------------------
/p18/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "database/sql"
6 | "fmt"
7 | "log"
8 | // 数据库驱动, _ 自我注册init 会自动调用。把包变成_ , 不会直接使用。
9 | //没有变量,不影响代码里面的逻辑
10 | _ "github.com/denisenkom/go-mssqldb"
11 | )
12 |
13 | var db *sql.DB // 指向数据库
14 | func main() {
15 | // 连接字符串
16 | connStr := fmt.Sprintf("server=%s;user id = %s; "+
17 | ""+
18 | "password=%s;port=%d;database=%s;",
19 | server, user, password, port, database)
20 | fmt.Println(connStr)
21 |
22 | db, err := sql.Open("sqlserver", connStr)
23 | if err != nil {
24 | log.Fatalln(err.Error())
25 | }
26 | ctx := context.Background()
27 |
28 | err = db.PingContext(ctx)
29 | if err != nil {
30 | log.Fatalln(err.Error())
31 | }
32 | // 测试是否连接数据库
33 | fmt.Println("connected!")
34 | }
35 |
36 | const (
37 | server = "xxxx.xxx"
38 | port = 1433
39 | user = "xxx"
40 | password = "123"
41 | database = "go-db"
42 | )
43 |
--------------------------------------------------------------------------------
/p19/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "database/sql"
6 | "fmt"
7 | "log"
8 | // 数据库驱动, _ 自我注册init 会自动调用。把包变成_ , 不会直接使用。
9 | //没有变量,不影响代码里面的逻辑
10 | _ "github.com/denisenkom/go-mssqldb"
11 | )
12 |
13 | var db *sql.DB // 指向数据库
14 | func main() {
15 | // 连接字符串
16 | connStr := fmt.Sprintf("server=%s;user id = %s; "+
17 | ""+
18 | "password=%s;port=%d;database=%s;",
19 | server, user, password, port, database)
20 | fmt.Println(connStr)
21 |
22 | var err error
23 | // 这个db 需要是全局的,不能用:=
24 | db, err = sql.Open("sqlserver", connStr)
25 | if err != nil {
26 | log.Fatalln(err.Error())
27 | }
28 | ctx := context.Background()
29 |
30 | err = db.PingContext(ctx)
31 | if err != nil {
32 | log.Fatalln(err.Error())
33 | }
34 | // 测试是否连接数据库
35 | fmt.Println("connected!")
36 |
37 | // 查询
38 | one, err := getOne(103)
39 | if err != nil {
40 | log.Fatalln(err.Error())
41 | }
42 | fmt.Println(one)
43 | }
44 |
45 | const (
46 | server = "xxxx.xxx"
47 | port = 1433
48 | user = "xxx"
49 | password = "123"
50 | database = "go-db"
51 | )
52 |
--------------------------------------------------------------------------------
/p19/model.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // 对应数据库的结构
4 | type app struct {
5 | ID int
6 | name string
7 | status int
8 | level int
9 | order int
10 | }
11 |
--------------------------------------------------------------------------------
/p19/service.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "database/sql"
5 | "log"
6 | )
7 |
8 | func getOne(id int) (a app, err error) {
9 | a = app{}
10 |
11 | // [order] 是sql里面的关键字,加上【】
12 | err = db.QueryRow("select id, name, status,"+
13 | "level, [order] from dbo.App").Scan(
14 | &a.ID, &a.name, &a.status, &a.level, &a.order)
15 | return
16 | }
17 |
18 | // 返回的切片【】
19 | func getMany(id int) (apps []app, err error) {
20 |
21 | // [order] 是sql里面的关键字,加上【】
22 | rows, err := db.Query("select id, name, status,"+
23 | "level, [order] from dbo.App where id > @id", sql.Named("Id", id))
24 |
25 | //对rows 遍历
26 |
27 | for rows.Next() {
28 | a := app{}
29 | err = rows.Scan(
30 | &a.ID, &a.name, &a.status, &a.level, &a.order)
31 | if err != nil {
32 | log.Fatalln(err.Error())
33 | }
34 | apps = append(apps, a)
35 | }
36 | return apps, err
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/p2/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "net/http"
4 |
5 | func main() {
6 | //mh := myHandler{} // 要使用的是这个指针
7 | //about := aboutHandler{}
8 | //hello := helloHandler{}
9 |
10 | //http.ListenAndServe("localhost:8080", nil)
11 |
12 | // 等价于上面一句话
13 | server := http.Server{
14 | Addr: ("localhost:8080"),
15 | Handler: nil,
16 | //Handler: &mh,
17 | }
18 | // 不同路径对应不用handler
19 | //http.Handle("/hello", &hello)
20 | //http.Handle("/about", &about)
21 | //http.Handle("/home", &mh)
22 |
23 | http.HandleFunc("/welcome", welcomeExample) // 这个不能是welcomeExample()
24 | server.ListenAndServe()
25 |
26 | }
27 |
28 | // 自定义http.handleFunc 函数, 形参和handler函数一样
29 | func welcomeExample(w http.ResponseWriter, r *http.Request) {
30 | w.Write([]byte("welcome!"))
31 | }
32 |
33 | // 自定义handler, 实现ServerHTTP 方法
34 | type myHandler struct {
35 | }
36 |
37 | // 自定义handler, 实现ServerHTTP 方法
38 | type helloHandler struct {
39 | }
40 |
41 | type aboutHandler struct {
42 | }
43 |
44 | //ServeHTTP 不是ServerHTTP
45 | func (m *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
46 | w.Write([]byte("home handler"))
47 | }
48 |
49 | func (m *helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
50 | w.Write([]byte("hello handler"))
51 | }
52 | func (m *aboutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
53 | w.Write([]byte("about handler"))
54 | }
55 |
--------------------------------------------------------------------------------
/p21/about.html:
--------------------------------------------------------------------------------
1 | {{ define "content"}}
2 |
3 | about: {{ . }}
4 |
5 | {{ end }}
--------------------------------------------------------------------------------
/p21/controller/about.go:
--------------------------------------------------------------------------------
1 | package controller
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 | "text/template"
7 | )
8 |
9 | // 注册路由
10 | func registerAboutRoutes() {
11 | http.HandleFunc("/about", handleAbout)
12 | }
13 |
14 | // handle处理逻辑
15 | func handleAbout(w http.ResponseWriter, r *http.Request) {
16 | t, err := template.ParseFiles("p21/layout.html", "p21/about.html")
17 | // 服务器没有数据,需要判err, open layout.html: The system cannot find the file specified.
18 | if err != nil {
19 | fmt.Println(err) // Ugly debug output
20 | w.WriteHeader(http.StatusInternalServerError) // Proper HTTP response , HTTP ERROR 500
21 | return
22 | }
23 | t.ExecuteTemplate(w, "about", "hello world")
24 | }
25 |
--------------------------------------------------------------------------------
/p21/controller/contact.go:
--------------------------------------------------------------------------------
1 | package controller
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 | "text/template"
7 | )
8 |
9 | // 注册路由
10 | func registerContactRoutes() {
11 | http.HandleFunc("/contact", handleContact)
12 | }
13 |
14 | // handle处理逻辑
15 | func handleContact(w http.ResponseWriter, r *http.Request) {
16 | t, err := template.ParseFiles("p21/layout.html", "p21/home.html")
17 | if err != nil {
18 | fmt.Printf("错误%v", err) // Ugly debug output
19 | w.WriteHeader(http.StatusInternalServerError) // Proper HTTP response
20 | return
21 | }
22 | t.ExecuteTemplate(w, "layout", "hello world")
23 | }
24 |
--------------------------------------------------------------------------------
/p21/controller/controller.go:
--------------------------------------------------------------------------------
1 | package controller
2 |
3 | // 路由总的入口
4 | func RegisterRoutes() {
5 |
6 | // static resources 写这里
7 |
8 | registerHomeRoutes()
9 | registerAboutRoutes()
10 | registerContactRoutes()
11 | }
12 |
--------------------------------------------------------------------------------
/p21/controller/home.go:
--------------------------------------------------------------------------------
1 | package controller
2 |
3 | import (
4 | "log"
5 | "net/http"
6 | "text/template"
7 | )
8 |
9 | // 注册路由
10 | func registerHomeRoutes() {
11 | http.HandleFunc("/home", handleHome)
12 | }
13 |
14 | // handle处理逻辑
15 | func handleHome(w http.ResponseWriter, r *http.Request) {
16 | t, e := template.ParseFiles("p21/layout.html", "p21/home.html")
17 | log.Println(e)
18 | t.ExecuteTemplate(w, "layout", "hello world")
19 | }
20 |
--------------------------------------------------------------------------------
/p21/home.html:
--------------------------------------------------------------------------------
1 | {{ define "content"}}
2 |
3 | Home: {{ . }}
4 |
5 | {{ end }}
--------------------------------------------------------------------------------
/p21/layout.html:
--------------------------------------------------------------------------------
1 | {{ define "content"}}
2 |
3 | layout: {{ . }}
4 |
5 | {{ end }}
--------------------------------------------------------------------------------
/p21/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "go-web-zero/p21/controller"
6 | "net/http"
7 | )
8 |
9 | func main() {
10 |
11 | /* 写在controller 里面
12 | http.HandleFunc("/home", func(w http.ResponseWriter, r *http.Request) {
13 | t, _ := template.ParseFiles("layout.html", "home.html")
14 | t.ExecuteTemplate(w, "layout", "hello world")
15 | })
16 |
17 | http.HandleFunc("/about", func(w http.ResponseWriter, r *http.Request) {
18 | t, _ := template.ParseFiles("layout.html", "about.html")
19 | t.ExecuteTemplate(w, "layout", "hello world")
20 | })
21 |
22 | http.HandleFunc("/contact", func(w http.ResponseWriter, r *http.Request) {
23 | t, e := template.ParseFiles("layout.html")
24 | t.ExecuteTemplate(w, "layout", "hello world")
25 | log.Println(e)
26 | })
27 | */
28 | fmt.Println("准备注册路由")
29 | controller.RegisterRoutes() // 注册路由,等价于上面的代码
30 | fmt.Println("已经注册路由")
31 | http.ListenAndServe("localhost:8080", nil) // 采用默认的多路复用器
32 | }
33 |
34 | // 问题,web 无任何内容???
35 |
--------------------------------------------------------------------------------
/p23/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "encoding/json"
5 | "go-web-zero/p23/middleware"
6 | "net/http"
7 | )
8 |
9 | type Company struct {
10 | ID int
11 | Name string
12 | Country string
13 | }
14 |
15 | func main() {
16 | http.HandleFunc("/companies", func(w http.ResponseWriter, r *http.Request) {
17 | c := Company{
18 | ID: 123,
19 | Name: "gggoolle",
20 | Country: "USA",
21 | }
22 | enc := json.NewEncoder(w)
23 | enc.Encode(c)
24 | })
25 | // 使用中间件
26 | http.ListenAndServe("localhost:8080", new(middleware.AuthMiddleware))
27 | }
28 |
--------------------------------------------------------------------------------
/p23/middleware/auth.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import "net/http"
4 |
5 | // 链式结构, Next 设置为 什么,下一个handler 就是什么
6 | // AuthMiddleware ..
7 | type AuthMiddleware struct {
8 | Next http.Handler
9 | }
10 |
11 | func (am *AuthMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
12 | // 如果只有一个中间件,改中间件的字段next 为nil, 交给默认路由器处理
13 | if am.Next == nil {
14 |
15 | am.Next = http.DefaultServeMux
16 | }
17 | // 判断auth
18 | auth := r.Header.Get("Authorization")
19 | if auth != "" {
20 | // before 路由
21 | am.Next.ServeHTTP(w, r)
22 | // after 路由
23 | } else {
24 | w.WriteHeader(http.StatusUnauthorized)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/p23/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Title
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/p23/test.http:
--------------------------------------------------------------------------------
1 | GET http://localhost:8080/companies HTTP/1.1
2 |
3 | # with auth
4 | GET http://localhost:8080/companies HTTP/1.1
5 | Authorization: aadfsafds
--------------------------------------------------------------------------------
/p24/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | func main() {
8 | fmt.Println("test tls")
9 | //http.ListenAndServeTLS("localhost:8080", nil, nil, nil)
10 | }
11 |
--------------------------------------------------------------------------------
/p3/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "net/http"
4 |
5 | func main() {
6 | mh := myHandler{} // 要使用的是这个指针
7 | about := aboutHandler{}
8 | hello := helloHandler{}
9 |
10 | //http.ListenAndServe("localhost:8080", nil)
11 |
12 | // 等价于上面一句话
13 | server := http.Server{
14 | Addr: ("localhost:8080"),
15 | Handler: nil,
16 | //Handler: &mh,
17 | }
18 | //不同路径对应不用handler
19 | http.Handle("/hello", &hello)
20 | http.Handle("/about", &about)
21 | http.Handle("/home", &mh)
22 |
23 | server.ListenAndServe()
24 |
25 | }
26 |
27 | // 自定义handler, 实现ServerHTTP 方法
28 | type myHandler struct {
29 | }
30 |
31 | // 自定义handler, 实现ServerHTTP 方法
32 | type helloHandler struct {
33 | }
34 |
35 | type aboutHandler struct {
36 | }
37 |
38 | //ServeHTTP 不是ServerHTTP
39 | func (m *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
40 | w.Write([]byte("home handler"))
41 | }
42 |
43 | func (m *helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
44 | w.Write([]byte("hello handler"))
45 | }
46 | func (m *aboutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
47 | w.Write([]byte("about handler"))
48 | }
49 |
--------------------------------------------------------------------------------
/p5/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 | )
7 |
8 | func main() {
9 | server := http.Server{
10 | Addr: "localhost:8080",
11 | Handler: nil,
12 | }
13 |
14 | http.HandleFunc("/post", func(w http.ResponseWriter, r *http.Request) {
15 | // 打印header
16 | fmt.Fprintln(w, r.Header)
17 |
18 | // 打印body
19 | length := r.ContentLength
20 | body := make([]byte, length)
21 | r.Body.Read(body)
22 | fmt.Fprintln(w, string(body)) // 结果写入到ResponseWrite 里面,需要转为字符串,才能看明白
23 |
24 | })
25 | server.ListenAndServe()
26 | }
27 |
--------------------------------------------------------------------------------
/p5/test.http:
--------------------------------------------------------------------------------
1 |
2 | # GET
3 | GET http://localhost:8080/header HTTP/1.1
4 |
5 | # POST test body
6 | POST http://localhost:8080/post HTTP/1.1
7 | content-type: application/json
8 | {
9 | "name":"sample"
10 | "time":"Wed, 21 Oct 2020 18:12:12 GMT"
11 | }
--------------------------------------------------------------------------------
/p6/img/img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/p6/img/img.png
--------------------------------------------------------------------------------
/p6/img/p6-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xkp58/go-web-zero/f1603f4ac140df4cc2b9c0fcb67b7535e04d840a/p6/img/p6-1.png
--------------------------------------------------------------------------------
/p6/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "net/http"
6 | )
7 |
8 | func main() {
9 | http.HandleFunc("/home", func(w http.ResponseWriter, r *http.Request) {
10 | url := r.URL
11 | query := url.Query()
12 |
13 | // 方法1:通过map,返回字符串切片
14 | id := query["id"]
15 | log.Println(id)
16 |
17 | // 方法2:通过Get方法,返回key对应的第一个值
18 | name := query.Get("name")
19 | log.Println(name)
20 |
21 | })
22 | http.ListenAndServe("localhost:8080", nil)
23 | }
24 |
25 | // 在浏览器输入:http://localhost:8080/home?id=001&name=xpk&id=002&name=zhuanma
26 |
--------------------------------------------------------------------------------
/p7/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | test Form
6 |
7 |
8 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/p7/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 | )
7 |
8 | func main() {
9 | server := http.Server{
10 | Addr: "localhost:8080",
11 | }
12 | http.HandleFunc("/process", func(w http.ResponseWriter, r *http.Request) {
13 | r.ParseForm()
14 | // r.Form 出现情况,url 里面的key 和 表单里面相同的话,会一起显示出来
15 | fmt.Fprintln(w, r.PostForm)
16 | })
17 | server.ListenAndServe()
18 | }
19 |
--------------------------------------------------------------------------------
/p8/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | load file
6 |
7 |
8 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/p8/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "io/ioutil"
6 | "net/http"
7 | )
8 |
9 | func process(w http.ResponseWriter, r *http.Request) {
10 | //r.ParseMultipartForm(1024)
11 | //
12 | //fileHeader := r.MultipartForm.File["uploaded"][0] // 获取上传的第一个文件
13 | //file, err := fileHeader.Open()
14 |
15 | file, _, err := r.FormFile("uploaded") // 传入的html form里面对应的key
16 | // 只会返回第一个文件,适合单文件上传
17 | if err == nil {
18 | data, err := ioutil.ReadAll(file)
19 | if err == nil {
20 | fmt.Fprintln(w, string(data))
21 | }
22 | }
23 |
24 | }
25 | func main() {
26 | server := http.Server{
27 | Addr: "localhost:8080",
28 | }
29 | http.HandleFunc("/process", process)
30 | server.ListenAndServe()
31 | }
32 |
--------------------------------------------------------------------------------
/p8/testloadfile.txt:
--------------------------------------------------------------------------------
1 | 20220503 beijing
2 | xpengkang
3 | xxxx
4 |
5 |
6 | xxxx
7 |
8 | x
9 | xx
10 | xxxx
11 | xfs1242142141241
12 | 12124124
13 | 1241241
14 |
15 |
16 | 12412412
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # go web zero(quickly start)
2 | 感谢up软件工艺师录制的go web 入门视频
3 | [source video](https://www.bilibili.com/video/BV1Xv411k7Xn?p=1)
4 |
5 |
6 |

7 |
8 |
9 | 以下是我跟着学习记录的笔记及各个视频对应的源代码
10 |
11 | ## p1 demo
12 | 一个web 打印hello, 只需两行代码!
13 | code:
14 | ~~~go
15 | package main
16 |
17 | import "net/http"
18 |
19 | func main() {
20 | // 调用适配器处理函数,两个参数,一个http地址,一个是hangler函数
21 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
22 | w.Write([]byte("hello go"))
23 | })
24 |
25 | //设置web 服务器,俩个参数,一个监听地址port,一个handler,默认是nil, 采用多路复用mux
26 | http.ListenAndServe("localhost:8080", nil)
27 |
28 | }
29 | ~~~
30 |
31 | 浏览器运行截图
32 |
33 | 
34 |
35 | ## p2 Handle 请求 上
36 | ~~~go
37 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
38 | w.Write([]byte("hello go"))
39 | })
40 | ~~~
41 | Handler 两个参数都是引用传递
42 |
43 | Handler Handler // handler to invoke, http.DefaultServeMux if nil
44 |
45 | 指针传递:w http.ResponseWriter,
46 | ResponseWriter是一个interface,代表了response的指针
47 | response是一个struct,他的指针实现了各种方法
48 | 指针传递:r *http.Request
49 |
50 | 
51 |
52 | 
53 |
54 | 源代码:
55 | http.Server 是一个struct
56 |
57 | 
62 | ~~~
63 | 我们可以自己定义server, 可配置方法:http.Server{}
64 | ~~~go
65 | // 等价于上面一句话
66 | server := http.Server{
67 | Addr: ("localhost:8080"),
68 | Handler: nil,
69 | }
70 | server.ListenAndServe()
71 | ~~~
72 |
73 | 理解Handler
74 |
75 | 1.这是一个接口
76 | 2.里面有ServeHTTP方法, 任何东西只要有这个方法就是Handler
77 |
78 | 3.DefaultServeMux 也是一个Handler
79 |
80 | 
81 |
82 |
83 | code
84 |
85 | ~~~go
86 | package main
87 |
88 | import "net/http"
89 |
90 | func main() {
91 | mh := myHandler{} // 要使用的是这个指针
92 |
93 | //http.ListenAndServe("localhost:8080", nil)
94 |
95 | // 等价于上面一句话
96 | server := http.Server{
97 | Addr: ("localhost:8080"),
98 | //Handler: nil,
99 | Handler: &mh,
100 | }
101 | server.ListenAndServe()
102 |
103 | }
104 |
105 | // 自定义handler, 实现ServerHTTP 方法
106 | type myHandler struct {
107 | }
108 |
109 | //ServeHTTP 不是ServerHTTP
110 | func (m *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
111 | w.Write([]byte("helllllllo my handler"))
112 | }
113 | ~~~
114 |
115 | 
116 |
117 |
118 |
119 |
120 |
121 | ## p3 Handle 请求 下
122 | 多个Hander
123 |
124 | 处理不同的路径/home, /about, /others
125 |
126 | 
127 | 两个参数:
128 |
129 |
130 | // 不同路径对应不用handler
131 | http.Handle("/hello", &hello)
132 | http.Handle("/about", &about)
133 | http.Handle("/home", &mh)
134 |
135 | code
136 | ~~~go
137 | package main
138 |
139 | import "net/http"
140 |
141 | func main() {
142 | mh := myHandler{} // 要使用的是这个指针
143 | about := aboutHandler{}
144 | hello := helloHandler{}
145 |
146 | //http.ListenAndServe("localhost:8080", nil)
147 |
148 | // 等价于上面一句话
149 | server := http.Server{
150 | Addr: ("localhost:8080"),
151 | Handler: nil,
152 | //Handler: &mh,
153 | }
154 | // 不同路径对应不用handler
155 | http.Handle("/hello", &hello)
156 | http.Handle("/about", &about)
157 | http.Handle("/home", &mh)
158 | server.ListenAndServe()
159 |
160 | }
161 |
162 | // 自定义handler, 实现ServerHTTP 方法
163 | type myHandler struct {
164 | }
165 |
166 | // 自定义handler, 实现ServerHTTP 方法
167 | type helloHandler struct {
168 | }
169 |
170 | type aboutHandler struct {
171 | }
172 |
173 | //ServeHTTP 不是ServerHTTP
174 | func (m *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
175 | w.Write([]byte("home handler"))
176 | }
177 |
178 | func (m *helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
179 | w.Write([]byte("hello handler"))
180 | }
181 | func (m *aboutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
182 | w.Write([]byte("about handler"))
183 | }
184 |
185 | ~~~
186 | 不同路径对应不用handler
187 |
188 | 
189 |
190 | 
191 |
192 | 第二个函数,http.HandleFunc
193 |
194 | 
195 |
196 | code
197 | ~~~go
198 |
199 | package main
200 |
201 | import "net/http"
202 |
203 | func main() {
204 |
205 | server := http.Server{
206 | Addr: ("localhost:8080"),
207 | Handler: nil,
208 | //Handler: &mh,
209 | }
210 | // 不同路径对应不用handler
211 | //http.Handle("/home", &mh)
212 | // 采用这个方法路由
213 | http.HandleFunc("/welcome", welcomeExample) // 这个不能是welcomeExample()
214 | server.ListenAndServe()
215 |
216 | }
217 |
218 | // 自定义http.handleFunc 函数, 形参和handler函数一样
219 | func welcomeExample(w http.ResponseWriter, r *http.Request) {
220 | w.Write([]byte("welcome!"))
221 | }
222 | ~~~
223 |
224 |
225 | 
226 |
227 |
228 | 总结:两个函数:
229 |
230 | 
231 |
232 | http.Handle 第一个参数路由路径“/home”
233 | 第二个参数 Handler
234 |
235 | http.HandleFunc 第一个参数路由路径“/home”
236 | 第二个参数 Handler **函数**(http.HandleFunc **将Handler函数转换为Handler**)
237 |
238 | ## p4 内置的Handlers
239 |
240 | 5 个
241 |
242 | 
243 |
244 | ## p5 Request
245 | Request 是一个struct, 表示请求消息
246 |
247 | 源码
248 |
249 | 
250 |
251 | url 是一个包, URL 是一个struct
252 | 
253 |
254 |
255 | ~~~go
256 | package main
257 |
258 | import (
259 | "fmt"
260 | "net/http"
261 | )
262 |
263 | func main() {
264 | server := http.Server{
265 | Addr: "localhost:8080",
266 | Handler: nil,
267 | }
268 |
269 | http.HandleFunc("/post", func(w http.ResponseWriter, r *http.Request) {
270 | // 打印header
271 | fmt.Fprintln(w, r.Header)
272 |
273 | // 打印body
274 | length := r.ContentLength
275 | body := make([]byte, length)
276 | r.Body.Read(body)
277 | fmt.Fprintln(w, string(body)) // 结果写入到ResponseWrite 里面,需要转为字符串,才能看明白
278 |
279 | })
280 | server.ListenAndServe()
281 | }
282 | ~~~
283 |
284 |
285 | ## p6
286 |
287 | query 操作
288 | 方法1:通过map,返回字符串切片
289 | id := query["id"]
290 |
291 | 方法2:通过Get方法,返回key对应的第一个值
292 | name := query.Get("name")
293 |
294 | ~~~go
295 | package main
296 |
297 | import (
298 | "log"
299 | "net/http"
300 | )
301 |
302 | func main() {
303 | http.HandleFunc("/home", func(w http.ResponseWriter, r *http.Request) {
304 | url := r.URL
305 | query := url.Query()
306 |
307 | // 方法1:通过map,返回字符串切片
308 | id := query["id"]
309 | log.Println(id)
310 |
311 | // 方法2:通过Get方法,返回key对应的第一个值
312 | name := query.Get("name")
313 | log.Println(name)
314 |
315 | })
316 | http.ListenAndServe("localhost:8080", nil)
317 | }
318 | ~~~
319 |
320 |
321 | ## p7
322 | [source video](https://www.bilibili.com/video/BV1Xv411k7Xn?p=7)
323 |
324 | 
325 |
326 | ~~~go
327 | package main
328 |
329 | import (
330 | "fmt"
331 | "net/http"
332 | )
333 |
334 | func main() {
335 | server := http.Server{
336 | Addr: "localhost:8080",
337 | }
338 | http.HandleFunc("/process", func(w http.ResponseWriter, r *http.Request) {
339 | r.ParseForm()
340 | // r.Form 出现情况,url 里面的key 和 表单里面相同的话,会一起显示出来
341 | fmt.Fprintln(w, r.PostForm)
342 | })
343 | server.ListenAndServe()
344 | }
345 | ~~~
346 | 结果: 使用r.Form
347 |
348 | 
349 |
350 | 结果:使用r.PostForm
351 |
352 | 
353 |
354 |
355 | index.html
356 | ~~~html
357 |
358 |
359 |
360 |
361 | test Form
362 |
363 |
364 |
371 |
372 |
373 |
374 | ~~~
375 |
376 | ## p8 上传文件
377 | 方法1
378 |
379 | 
380 |
381 |
382 |
383 | ~~~go
384 | package main
385 |
386 | import (
387 | "fmt"
388 | "io/ioutil"
389 | "net/http"
390 | )
391 |
392 | func process(w http.ResponseWriter, r *http.Request) {
393 | r.ParseMultipartForm(1024)
394 |
395 | fileHeader := r.MultipartForm.File["uploaded"][0] // 获取上传的第一个文件
396 | file, err := fileHeader.Open()
397 | if err == nil {
398 | data, err := ioutil.ReadAll(file)
399 | if err == nil {
400 | fmt.Fprintln(w, string(data))
401 | }
402 | }
403 |
404 | }
405 | func main() {
406 | server := http.Server{
407 | Addr: "localhost:8080",
408 | }
409 | http.HandleFunc("/process", process)
410 | server.ListenAndServe()
411 | }
412 | ~~~
413 |
414 |
415 | 成功读取文件
416 |
417 | 
418 |
419 | 方法2
420 |
421 | 
422 |
423 | ~~~go
424 | package main
425 |
426 | import (
427 | "fmt"
428 | "io/ioutil"
429 | "net/http"
430 | )
431 |
432 | func process(w http.ResponseWriter, r *http.Request) {
433 | //r.ParseMultipartForm(1024)
434 | //
435 | //fileHeader := r.MultipartForm.File["uploaded"][0] // 获取上传的第一个文件
436 | //file, err := fileHeader.Open()
437 |
438 | file, _, err := r.FormFile("uploaded") // 传入的html form里面对应的key
439 | // 只会返回第一个文件,适合单文件上传
440 | if err == nil {
441 | data, err := ioutil.ReadAll(file)
442 | if err == nil {
443 | fmt.Fprintln(w, string(data))
444 | }
445 | }
446 |
447 | }
448 | func main() {
449 | server := http.Server{
450 | Addr: "localhost:8080",
451 | }
452 | http.HandleFunc("/process", process)
453 | server.ListenAndServe()
454 | }
455 | ~~~
456 |
457 | index.html
458 | ~~~html
459 |
460 |
461 |
462 |
463 | load file
464 |
465 |
466 |
475 |
476 |
477 |
478 | ~~~
479 |
480 | 解析JSON(视频里留坑,没有讲)
481 |
482 | 
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 | ## p9
492 | 无栗子
493 |
494 | 
495 |
496 | ## p10 ResponseWriter
497 |
498 | ~~~go
499 | package main
500 |
501 | import "net/http"
502 |
503 | func writeExample(w http.ResponseWriter, r *http.Request) {
504 | str := `
505 |
506 |
507 |
508 | Go web
509 |
510 |
511 | hello go go go world
512 |
513 | `
514 |
515 | w.Write([]byte(str)) // 把str 写入到body 里面, 需要类型转换
516 | }
517 | func main() {
518 |
519 | server := http.Server{
520 | Addr: "localhost:8080",
521 | }
522 | http.HandleFunc("/write", writeExample)
523 | server.ListenAndServe()
524 |
525 | }
526 | ~~~
527 |
528 |
529 | 写入结果:
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 | 写入json到web 里面
539 |
540 | 
541 |
542 | 源代码:
543 | ~~~go
544 | package main
545 |
546 | import (
547 | "encoding/json"
548 | "net/http"
549 | )
550 |
551 | func writeExample(w http.ResponseWriter, r *http.Request) {
552 | str := `
553 |
554 |
555 |
556 | Go web
557 |
558 |
559 | hello go go go world
560 |
561 | `
562 |
563 | w.Write([]byte(str)) // 把str 写入到body 里面, 需要类型转换
564 | }
565 |
566 | func headerExample(w http.ResponseWriter, r *http.Request) {
567 | w.Header().Set("Location", "http://baidu.com")
568 | // 必须调用前修改header
569 | w.WriteHeader(302) // 重定向302
570 | }
571 |
572 | type POST struct {
573 | User string
574 | Thread []string
575 | }
576 |
577 | func jsonExample(w http.ResponseWriter, r *http.Request) {
578 | w.Header().Set("Content-Type", "application/json")
579 | post := &POST{
580 | User: "xxpkk",
581 | Thread: []string{"first", "second", "third"},
582 | }
583 | json, _ := json.Marshal(post)
584 | w.Write(json)
585 | }
586 |
587 | func main() {
588 |
589 | server := http.Server{
590 | Addr: "localhost:8080",
591 | }
592 | http.HandleFunc("/write", writeExample)
593 | http.HandleFunc("/redirect", headerExample)
594 |
595 | //json 案例
596 | http.HandleFunc("/json", jsonExample)
597 | server.ListenAndServe()
598 |
599 | }
600 | ~~~
601 |
602 |
603 | ## p11 内置的响应Response
604 |
605 |
606 | ## p12 模板 [video](https://www.bilibili.com/video/BV1Xv411k7Xn?p=12)
607 |
608 | 
609 |
610 | 原理
611 |
612 | 
613 |
614 | 课程代码
615 | ~~~go
616 | package main
617 |
618 | import (
619 | "html/template"
620 | "net/http"
621 | )
622 |
623 | // 自定义的handler
624 | func process(w http.ResponseWriter, r *http.Request) {
625 | // 解析模板文件,相对路径
626 | t, _ := template.ParseFiles("tmpl.html")
627 | // 执行模板,传入数据,替换{{.}}
628 | t.Execute(w, "hello go go go go")
629 | }
630 |
631 | func main() {
632 | server := http.Server{
633 | Addr: "localhost:8080",
634 | }
635 | http.HandleFunc("/test", process)
636 | server.ListenAndServe()
637 | }
638 | ~~~
639 |
640 | ## p13
641 |
642 | 源码解读:
643 |
644 | 解析模板源(可以是字符串或模板文件),从而创建一个解析好的模板的 struct
645 | 执行解析好的模板,并传入 ResponseWriter 和 数据。
646 | 这会触发模板引擎组合解析好的模板和数据,来产生最终的 HTML,并将它传递给 ResponseWriter
647 |
648 | 
649 |
650 |
651 | code
652 | ~~~go
653 | package main
654 |
655 | import (
656 | "html/template"
657 | "net/http"
658 | )
659 |
660 | func main() {
661 |
662 | server := http.Server{
663 | Addr: "localhost:8080",
664 | }
665 | http.HandleFunc("/process", process)
666 | server.ListenAndServe()
667 |
668 | }
669 |
670 | func process(w http.ResponseWriter, r *http.Request) {
671 | //解析1个模板
672 | t, _ := template.ParseFiles("tmpl.html")
673 | t.Execute(w, "hello go")
674 | ////等价于下面两句话
675 | //t := template.New("tmpl.html")
676 | //t, _ = t.ParseFiles("tmpl.html")
677 |
678 | //t1,_, := template.ParseGlob("*.html")
679 |
680 | //解析多个模板
681 | ts, _ := template.ParseFiles("t1.html", "t2.html")
682 | ts.ExecuteTemplate(w, "t2.html", "hello go t2")
683 |
684 | }
685 |
686 | ~~~
687 |
688 |
689 |
690 |
691 | 执行出错
692 |
693 | 
694 |
695 | 
696 |
697 |
698 | ## p14 demo 模板执行与解析
699 |
700 | ## p18 链接数据库
701 |
702 | 连接到数据库
703 |
704 | 解决加载驱动问题,这里设置一下代理,就能正常下载github资源了
705 |
706 | 
707 |
708 | [go代理](https://cloud.tencent.com/developer/article/1773630)
709 |
710 | func(*DB) pingContext 函数
711 |
712 | 
713 |
714 | ~~~go
715 | package main
716 |
717 | import (
718 | "context"
719 | "database/sql"
720 | "fmt"
721 | "log"
722 | // 数据库驱动, _ 自我注册init 会自动调用。把包变成_ , 不会直接使用。
723 | //没有变量,不影响代码里面的逻辑
724 | _ "github.com/denisenkom/go-mssqldb"
725 | )
726 |
727 | var db *sql.DB // 指向数据库
728 | func main() {
729 | // 连接字符串
730 | connStr := fmt.Sprintf("server=%s;user id = %s; "+
731 | ""+
732 | "password=%s;port=%d;database=%s;",
733 | server, user, password, port, database)
734 | fmt.Println(connStr)
735 |
736 | db, err := sql.Open("sqlserver", connStr)
737 | if err != nil {
738 | log.Fatalln(err.Error())
739 | }
740 | ctx := context.Background()
741 |
742 | err = db.PingContext(ctx)
743 | if err != nil {
744 | log.Fatalln(err.Error())
745 | }
746 | // 测试是否连接数据库
747 | fmt.Println("connected!")
748 | }
749 |
750 | const (
751 | server = "xxxx.xxx"
752 | port = 1433
753 | user = "xxx"
754 | password = "123"
755 | database = "go-db"
756 | )
757 | ~~~
758 |
759 | ## p19 数据库的查询
760 |
761 | 
762 |
763 |
764 |
765 | main.go
766 | ~~~go
767 | package main
768 |
769 | import (
770 | "context"
771 | "database/sql"
772 | "fmt"
773 | "log"
774 | // 数据库驱动, _ 自我注册init 会自动调用。把包变成_ , 不会直接使用。
775 | //没有变量,不影响代码里面的逻辑
776 | _ "github.com/denisenkom/go-mssqldb"
777 | )
778 |
779 | var db *sql.DB // 指向数据库
780 | func main() {
781 | // 连接字符串
782 | connStr := fmt.Sprintf("server=%s;user id = %s; "+
783 | ""+
784 | "password=%s;port=%d;database=%s;",
785 | server, user, password, port, database)
786 | fmt.Println(connStr)
787 |
788 | var err error
789 | // 这个db 需要是全局的,不能用:=
790 | db, err = sql.Open("sqlserver", connStr)
791 | if err != nil {
792 | log.Fatalln(err.Error())
793 | }
794 | ctx := context.Background()
795 |
796 | err = db.PingContext(ctx)
797 | if err != nil {
798 | log.Fatalln(err.Error())
799 | }
800 | // 测试是否连接数据库
801 | fmt.Println("connected!")
802 |
803 | // 查询
804 | one, err := getOne(103)
805 | if err != nil {
806 | log.Fatalln(err.Error())
807 | }
808 | fmt.Println(one)
809 | }
810 |
811 | const (
812 | server = "xxxx.xxx"
813 | port = 1433
814 | user = "xxx"
815 | password = "123"
816 | database = "go-db"
817 | )
818 | ~~~
819 |
820 |
821 | model 对应数据库的结构
822 | ~~~go
823 | package main
824 |
825 | // 对应数据库的结构
826 | type app struct {
827 | ID int
828 | name string
829 | status int
830 | level int
831 | order int
832 | }
833 | ~~~
834 |
835 | service :sql 语句
836 | ~~~go
837 | package main
838 |
839 | func getOne(id int) (a app, err error) {
840 | a = app{}
841 |
842 | // [order] 是sql里面的关键字,加上【】
843 | err = db.QueryRow("select id, name, status,"+
844 | "level, [order] from dbo.App").Scan(
845 | &a.ID, &a.name, &a.status, &a.level, &a.order)
846 | return
847 | }
848 | ~~~
849 |
850 | ## p20 crud
851 | 多行查询
852 | ~~~go
853 | // 返回的切片【】
854 | func getMany(id int) (apps []app, err error) {
855 |
856 | // [order] 是sql里面的关键字,加上【】
857 | rows, err := db.Query("select id, name, status,"+
858 | "level, [order] from dbo.App where id > @id", sql.Named("Id", id))
859 |
860 | //对rows 遍历
861 |
862 | for rows.Next() {
863 | a := app{}
864 | err = rows.Scan(
865 | &a.ID, &a.name, &a.status, &a.level, &a.order)
866 | if err != nil {
867 | log.Fatalln(err.Error())
868 | }
869 | apps = append(apps, a)
870 | }
871 | return apps, err
872 |
873 | }
874 | ~~~
875 |
876 |
877 |
878 |
879 | # p21 路由
880 |
881 | 针对不同的路径,使用不同的handler
882 |
883 | **之前的代码都在main 函数里面,不符合项目架构** 增加control 层
884 |
885 | main():设置类工作
886 |
887 | controller:
888 | 静态资源
889 | 把不同的请求送到不同的 controller 进行处理
890 |
891 | 
892 |
893 |
894 |
895 | ## p22
896 |
897 | go 和json 属性映射
898 |
899 | 
900 |
901 | 
902 |
903 |
904 |
905 | ## p23 中间件
906 |
907 | 
908 |
909 | 只要实现ServeHTTP 方法就可
910 |
911 | main.go
912 | ~~~go
913 | package main
914 |
915 | import (
916 | "encoding/json"
917 | "go-web-zero/p23/middleware"
918 | "net/http"
919 | )
920 |
921 | type Company struct {
922 | ID int
923 | Name string
924 | Country string
925 | }
926 |
927 | func main() {
928 | http.HandleFunc("/companies", func(w http.ResponseWriter, r *http.Request) {
929 | c := Company{
930 | ID: 123,
931 | Name: "gggoolle",
932 | Country: "USA",
933 | }
934 | enc := json.NewEncoder(w)
935 | enc.Encode(c)
936 | })
937 | // 使用中间件
938 | http.ListenAndServe("localhost:8080", new(middleware.AuthMiddleware))
939 | }
940 | ~~~
941 |
942 | auth.go
943 | ~~~go
944 | package middleware
945 |
946 | import "net/http"
947 |
948 | // 链式结构, Next 设置为 什么,下一个handler 就是什么
949 | // AuthMiddleware ..
950 | type AuthMiddleware struct {
951 | Next http.Handler
952 | }
953 |
954 | func (am *AuthMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
955 | // 如果只有一个中间件,改中间件的字段next 为nil, 交给默认路由器处理
956 | if am.Next == nil {
957 |
958 | am.Next = http.DefaultServeMux
959 | }
960 | // 判断auth
961 | auth := r.Header.Get("Authorization")
962 | if auth != "" {
963 | // before 路由
964 | am.Next.ServeHTTP(w, r)
965 | // after 路由
966 | } else {
967 | w.WriteHeader(http.StatusUnauthorized)
968 | }
969 | }
970 | ~~~
971 |
972 | 测试:
973 | ~~~html
974 | GET http://localhost:8080/companies HTTP/1.1
975 |
976 | # with auth
977 | GET http://localhost:8080/companies HTTP/1.1
978 | Authorization: aadfsafds
979 | ~~~
980 |
981 | 
982 |
983 |
984 | ## p25 https
985 |
986 | 
987 | http.ListenAndServeTLS() 需要四个参数
988 |
989 |
990 | ## p27 测试
991 |
992 | 
993 |
994 | ## p28 性能分析
995 |
996 | 
997 |
998 | 
999 |
1000 | ## p29 部署
1001 | Linux 部署
1002 |
1003 | 
1004 |
1005 |
1006 | # p30 CRUD 栗子
1007 |
1008 |
1009 | # 完结撒花
1010 |
1011 | 都看到这里了,点个star吧:P
1012 |
1013 |
1014 |
1015 |
1016 |
1017 |
--------------------------------------------------------------------------------