返回数据

- 最简单的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. Java实现文本中的关键字高亮,匹配所有长度

    这个方法还不完整,后面想起来再看,直接放代码 public static String getHeightlightWord(String textWord, String key){ StringB ...

  2. jar包编译成 dex

    1.将需要合并的jar放到同一个目录 2.编写一个google.xml文件写入如下内容 <!--?xml version="1.0" encoding="utf-8 ...

  3. odoo标识符

    class Book(models.Model): _name = "library.book" _description = "Book" _order = ...

  4. python常用模块:项目目录规范、定制程序入口、自定义模块、引用变量、time和datetime模块

    今天讲课内容有两大部分: 一.文件目录规范二.定制程序入口三.使用标准目录后四.常规函数time.datetime 一.标准目录规范 之前用过的案例atm机+购物商城代码过长,在学习了模块和包以后,我 ...

  5. 开关灯 ToggleButton

    开关灯 ToggleButton textOn:对应true的时候:textOff:对应false的时候:给toggleButton设置监听器toggleButton.setOnCheckChange ...

  6. windows漏洞MS03_026

    话不多说,直接进入正题 第一步查看是否能ping通,第二步就是扫描端口,开放了端口才能进行攻击 linux进入msfconsole,搜索03_026 search 03_026 等待一会,返回漏洞的全 ...

  7. 数据库——Oracle(8)

    1 标准SQL外连接(二) 1) 全外连接:查询所有表所有的数据 格式: select 别名1.*/列名,别名2.*/列名 from 表1 别名1 full outer join 表2 别名2 on ...

  8. HH的项链 HYSBZ - 1878 (莫队/ 树状数组)

    HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一 段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此他的项链变得越来越长.有一天,他突然 ...

  9. java线程基础巩固---多线程与JVM内存结构的关系及Thread构造函数StackSize的理解

    继续学习一下Thread的构造函数,在上次[http://www.cnblogs.com/webor2006/p/7760422.html]已经对如下构造都已经学习过了: 多线程与JVM内存结构的关系 ...

  10. for(auto count:counts)

    c++中for(auto count : counts) 这是C++11中的语法,即:Range-based for loop.其中counts应满足:begin(counts), end(count ...