返回数据

- 最简单的http服务

package main

import (
"net/http"
) func main() {
http.ListenAndServe(":8080", nil)
}
  • 返回字符串
- 挂载路由节点
//例1:
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello http"))
})
http.ListenAndServe(":8080", nil)
} //例2
package main import (
"net/http"
) func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "hello world")
})
log.Fatal(http.ListenAndServe(":8080", nil))
} //例3:
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "hello world2")
})
http.ListenAndServe(":8080", nil)
}
- 启动http接口

package main

import (
"io"
"log"
"net/http"
) func main() {
h1 := func(w http.ResponseWriter, _ *http.Request) {
io.WriteString(w, "Hello from a HandleFunc #1!\n")
}
h2 := func(w http.ResponseWriter, _ *http.Request) {
io.WriteString(w, "Hello from a HandleFunc #2!\n")
} http.HandleFunc("/", h1)
http.HandleFunc("/endpoint", h2) log.Fatal(http.ListenAndServe(":8080", nil))
}
  • 返回json
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("content-type", "application/json; charset=utf-8")
w.Write([]byte(`{"code":-1, "msg":"no such file我"}`))
})
http.ListenAndServe(":8080", nil)
}
- 例子: 读取data.json,返回json
- data.json
[
{
"name": "mm",
"age": 22
}
] type User struct {
Name string `json:"name"`
Age int `json:"age"`
} var data []User func LoadData() {
var content, err = ioutil.ReadFile("data.json")
if err != nil {
fmt.Println(err.Error())
} json.Unmarshal(content, &data)
fmt.Println(data)
} func main() {
LoadData() // CRUD endpoint functions
u := func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(data)// 1.json写入io.Writer/os.Stdout
// 2.[普通marshell]json和data之间转换
} http.HandleFunc("/user", u)
http.ListenAndServe(":8080", nil)
}

获取参数

// GET localhost:8080/?name=mm&age=22
Content-Type: "" //request的Content-Type值为"" //参数携带在了url(Query String Parameters)
name=m1&age=22 // body内容为空 func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
r.ParseForm() //将参数解析到一个map里 fmt.Println(r.Form) //map[age:[22] name:[mm]]
name := r.Form["name"][0] fmt.Println(name)
io.WriteString(w, "hi")
})
http.ListenAndServe(":8080", nil)
}
//mm
//GET localhost:8080/?name=m1&name=m2&age=22
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
r.ParseForm() fmt.Println(r.Form) //map[age:[22] name:[m1 m2]] name1 := r.Form["name"][0]
name2 := r.Form["name"][1] fmt.Println(name1, name2)
io.WriteString(w, "hi")
})
http.ListenAndServe(":8080", nil)
} //m1 m2
// GET localhost:8080/?name=mm&age=22

func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
name := r.Form.Get("name") //使用url.Values(map)封装的GET方法取值
age := r.Form.Get("age")
fmt.Println(name, age)
io.WriteString(w, "hi")
})
http.ListenAndServe(":8080", nil)
}
//mm 22
- form提交默认是get.(和GET携带参数处理方式一样)
<body>
<form action="http://localhost:8080/">
<input type="text" name="name">
<input type="text" name="age">
<input type="submit">
</form>
</body> Content-Type: "" //request的Content-Type值为"" //数据(参数)携带在了url(Query String Parameters )
name=admin&age=123456 // body内容为空 func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
r.ParseForm() //将参数解析到一个map里
fmt.Println(r.Form) //map[age:[123456] name:[admin]] io.WriteString(w, "hi")
})
http.ListenAndServe(":8080", nil)
}
- 表单请求
<body>
<form action="http://localhost:8080/" method="post">
<input type="text" name="name">
<input type="text" name="age">
<input type="submit">
</form>
</body> //默认将request的Content-Type设置为
Content-Type: application/x-www-form-urlencoded //将数据携带在了body(Form Data):
name=m1&age=22 func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { body, _ := ioutil.ReadAll(r.Body)
fmt.Println(string(body)) //name=m1&age=22 io.WriteString(w, "hi")
})
http.ListenAndServe(":8080", nil)
}
- 上面这种情况,解析表单参数

func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { r.ParseForm() //将参数解析到一个map里
fmt.Println(r.Form) //map[age:[22] name:[mm]]
io.WriteString(w, "hi")
})
http.ListenAndServe(":8080", nil)
}
- 解析post body: json data

POST localhost:8080
Content-Type: application/json;charset=UTF-8 {
"name": "m1",
"age": 22
} // Content-Type: application/json;charset=UTF-8 //数据携带在body(Request Payload)
{"name":"mm","age":22} func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
body, _ := ioutil.ReadAll(r.Body)
//fmt.Fprintf(w, "%s", body)
user := User{}
err := json.Unmarshal(body, &user)
if err != nil {
fmt.Println(err)
}
fmt.Println(user)
})
http.ListenAndServe(":8080", nil)
}

文件上传下载

  • 文件下载
- 简单的web 文件服务
func main() {
// Simple static webserver:
log.Fatal(http.ListenAndServe(":3001", http.FileServer(http.Dir("."))))
}
- 伪url访问真实目录
func main() {
// To serve a directory on disk (/tmp) under an alternate URL
// path (/tmpfiles/), use StripPrefix to modify the request
http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("."))))
http.ListenAndServe(":3001", nil)
}
  • 文件上传
- request:
Content-Type: multipart/form-data; - 文件上传的表单
Content-Disposition 属性是作为对下载文件的一个标识字段
如果有type=file的话,就要用到multipart/form-data了。
浏览器会把整个表单以控件为单位分割,
并为每个部分加上
Content-Disposition(form-data或者file),
Content-Type(默认为text/plain),
name(控件name)等信息, 并加上分割符(boundary)。 <body>
<form action="http://localhost:8080/" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit">
</form>
</body> - 请求body: 内容里Content-Type会自动感知为对应文件类型
------WebKitFormBoundary9Px0BT0GcBlQEiUO
Content-Disposition: form-data; name="file"; filename="app.json"
Content-Type: application/json {
"name": "Start on Heroku: Go",
"description": "Go Getting Started Example App",
"keywords": [
"getting-started",
"go",
"sample",
"example"
],
"image": "heroku/go:1.6",
"mount_dir": "src/github.com/heroku/go-getting-started",
"website": "http://github.com/heroku/go-getting-started",
"repository": "http://github.com/heroku/go-getting-started"
} ------WebKitFormBoundary9Px0BT0GcBlQEiUO-- func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { body, _ := ioutil.ReadAll(r.Body)
fmt.Println(string(body))
w.Write([]byte("hi")) //r.ParseMultipartForm(32 << 20)
//file, handler, err := r.FormFile("file")
//if err != nil {
// w.WriteHeader(http.StatusInternalServerError)
// w.Write([]byte("解析表单出错"))
// return
//}
//defer file.Close()
//f, err := os.OpenFile(handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
//if err != nil {
// w.WriteHeader(http.StatusInternalServerError)
// w.Write([]byte("写入文件出错"))
// return
//}
//defer f.Close()
//io.Copy(f, file)
})
http.ListenAndServe(":8080", nil)
}

如果传的是图片, 则会展示一些乱码

常用方法

  • 区分http方法: r.Method
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
io.WriteString(w, "get")
} else if r.Method == "POST" {
io.WriteString(w, time.Now().Format("post: 2006-01-02 15:04:05"))
}
})
http.ListenAndServe(":8080", nil)
}
- w.Write后面语句会执行
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hi"))
fmt.Println("123213123")
}) http.ListenAndServe(":3000", nil)
} //return后不再执行
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hi"))
return
fmt.Println("123213123")
}) http.ListenAndServe(":3000", nil)
}
- 读文件,返回文件
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
data, err := ioutil.ReadFile("./static/view/signup2.html")
if err != nil {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte(err.Error()))
return
}
w.Write(data)
}) http.ListenAndServe(":3000", nil)
}
r.Method == "GET"
time.Now().Format("2006-01-02 15:04:05") //文件操作 os.Create(fileMeta.Location)
io.Copy(newFile, file)
os.Remove(fMeta.Location) ioutil.ReadFile("./static/view/index.html")
os.Open(fm.Location)
ioutil.ReadAll(f)
newFile.Seek(0, 0) //获取GET参数
// - 方法1
r.ParseForm()
op := r.Form.Get("op") // - 方法2
r.ParseForm()
op := r.Form["op"][0] // 小结: 表单post过来的格式和 get方法通过路径携带参数 提交过来的格式 是一致的. //获取表单提交字段数据
// - 方法1
r.ParseForm()
op := r.Form.Get("op") // - 方法2
r.ParseForm()
filehash := r.Form["filehash"][0] //表单传文件
file, head, err := r.FormFile("file") // <form action="http://localhost:8081/upload" method="post" enctype="multipart/form-data"> w.Write([]byte("Upload Failed."))
w.Write([]byte(`{"code":-1,"msg":"no such file"}`))
io.WriteString(w, "internel server error") //设置下载头
w.Header().Set("Content-Type", "application/octect-stream")
w.Header().Set("content-disposition", "attachment; filename=\""+fm.FileName+"\"") //设置跨域头
w.Header().Set("Access-Control-Allow-Origin", "*") //允许访问所有域
w.Header().Add("Access-Control-Allow-Headers", "Content-Type") //header的类型
w.Header().Set("content-type", "application/json") //TODO: 设置全局跨域中间件 w.WriteHeader(http.StatusOK)
w.WriteHeader(http.StatusInternalServerError)
w.WriteHeader(http.StatusMethodNotAllowed)
w.WriteHeader(http.StatusForbidden) http.Redirect(w, r, "/static/view/home.html", http.StatusFound) fmt.Println(err.Error())
// http包基础使用

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

})
http.ListenAndServe(":3000", nil)
// http包进阶使用

//初始化路由
mux = http.NewServeMux()
mux.HandleFunc("/job/save", handleJobSave) //设置静态目录
staticDir = http.Dir(G_config.WebRoot)
staticHandler = http.FileServer(staticDir)
mux.Handle("/", http.StripPrefix("/", staticHandler)) listener, err = net.Listen("tcp", ":" + strconv.Itoa(G_config.ApiPort)); //创建http服务器
httpServer = &http.Server{
ReadTimeout: time.Duration(G_config.ApiReadTimeout) * time.Millisecond,
WriteTimeout: time.Duration(G_config.ApiWriteTimeout) * time.Millisecond,
Handler: mux,
} go httpServer.Serve(listener)

net/http模块架构

前后端交互数据

通过表单提交

// 前端表单提交

<form action="http://localhost:8000/" method="post">
<input type="text" name="username">
<input type="text" name="password">
<input type="submit">
</form>

//后端接收

r.ParseForm()
username := r.Form.Get("username") //接收到的都是字符串

前端ajax post提交json

// 前端ajax post提交json

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
</head>
<body>
<div id="app">
<button @click="postData">postData</button>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script src="node_modules/axios/dist/axios.js"></script>
<script>
let vm = new Vue({
el: "#app",
methods: {
postData() {
axios.post("http://localhost:8000/", {
"username": "m1",
"password": 123456
})
}
}
});
</script>
</body>
</html>

参考

type LoginInfo struct {
Username string `json:username`
Password int `json:password`
} body, _ := ioutil.ReadAll(r.Body)
var loginInfo LoginInfo
json.Unmarshal(body, &loginInfo)
fmt.Println(loginInfo)

最新文章

  1. 创建自己的Vagrant box
  2. BZOJ 3732 Network
  3. rpm常用命令
  4. ImageView
  5. MySQL触发器如何正确使用
  6. App 打包并跳过 AppStore 的发布下载
  7. linux_c学习笔记之curl的使用一
  8. 【Android】以SimpleAdapter做适配器的ListView和GridView
  9. cocos js响应过程
  10. export-data.js
  11. IOS 9人机界面指南(1)
  12. Luogu 1349 广义斐波那契数列(递推,矩阵,快速幂)
  13. treeview调用数据库成树
  14. Status bar could not find cached time string image. Rendering in-process?
  15. 【模板】cdq分治代替树状数组(单点修改,区间查询)
  16. 深度学习卷积网络中反卷积/转置卷积的理解 transposed conv/deconv
  17. Android 播放内部mp3音乐
  18. Python时间系统
  19. A标签href属性详解--记录八
  20. setOnPageChangeListener 过时了怎么办?

热门文章

  1. remote mounting from windows to linux
  2. 十二,k8s集群访问控制之RBAC授权
  3. qunee 流动的关系
  4. linux-Redhat7 windows物理机与虚拟机设置共享目录
  5. 版本控制工具 svn 二
  6. C++——函数
  7. less 分页显示文件内容
  8. 牛客小白月赛12 H 华华和月月种树 (离线dfs序+线段树)
  9. linux 发送 post 请求
  10. gtid 同步1050异常处理