因为我是学Java的,主要做web开发,所以看了点go的基础知识后,就试着把以前的demo用go实现以下,而且go web开发非常简便只要几行代码,就能实现简单http服务器,今天主要写一下用net/http包模拟客户端发送请求实现百度推送(实时)。

开始

项目结构

.
├── static
|   ├── css
|   └── layer
├── views
|   └── index.html
└── main.go

main.go

package main

import (
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strings"
)

func main() {
	http.HandleFunc("/", index)
	http.HandleFunc("/send", bdSend)
	//处理静态文件
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
	err := http.ListenAndServe(":80", nil)
	if err != nil {
		log.Fatal(err)
	}
}

//首页
func index(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" {
		t, err := template.ParseFiles("views/index.html")
		if err != nil {
			log.Fatal(err)
		}
		t.Execute(w, nil)
	}
}

//推送
func bdSend(w http.ResponseWriter, r *http.Request) {
	if r.Method == "POST" {
		request(w, r)
	}
}

//模拟http客户端post发送请求
func request(w http.ResponseWriter, r *http.Request) {
	//先解析form
	err := r.ParseForm()
	
	if err != nil {
		log.Fatal(err)
	}
	//请求地址
	var apiURL string
	switch r.Form["oper"][0] {
	case "post":
		apiURL = "http://data.zz.baidu.com/urls"
	case "update":
		apiURL = "http://data.zz.baidu.com/update"
	case "del":
		apiURL = "http://data.zz.baidu.com/del"
	}

	//初始化参数
	param := url.Values{}

	//配置请求参数,方法内部已处理urlencode问题,中文参数可以直接传参
	param.Set("site", r.Form["site"][0])
	param.Set("token", r.Form["token"][0])

	var URL *url.URL
	URL, err = url.Parse(apiURL)
	if err != nil {
		fmt.Printf("解析url错误:\r\n%v", err)
	}
	//如果参数中有中文参数,这个方法会进行URLEncode
	URL.RawQuery = param.Encode()
	client := &http.Client{}
	req, _ := http.NewRequest("POST", URL.String(), strings.NewReader(r.Form["sendURL"][0]))

	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	//req.Header.Set("User-Agent", "curl/7.12.1")
	//req.Header.Set("Host", "data.zz.baidu.com")

	//发送请求
	resp, err := client.Do(req)
	//注意关闭resp.Body
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("请求失败,错误信息:\r\n%v", err)
	} else {
		//var returns map[string]interface{}
		//json.Unmarshal(data, &returns)
		//data, err = json.Marshal(returns)
		//将返回的json数据返给客户端浏览器
		fmt.Fprintln(w, string(data))
	}
}

index.html

<!DOCTYPE html>
<html lang="zh-CN">
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
		<title>百度主动推送(实时)</title>
		<LINK rel="Bookmark" href="/static/favicon.ico">
		<LINK rel="Shortcut Icon" href="/static/favicon.ico" />
		<!-- Bootstrap -->
		<link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
		<link rel="stylesheet" href="/static/css/style.css">
		<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
		<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
		<!--[if lt IE 9]>
			<script src="//cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
			<script src="//cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
	    <![endif]-->
	</head>
	<body class="bg-body">
		<div class="container text-center bg">
			<h1>百度主动推送(实时)</h1>
			<form class="form-horizontal" id="form" >
				<div class="form-group  form-group-lg">
					<div class="col-sm-8 col-sm-offset-2">
						<select class="form-control" id="oper" name="oper">
							<option value="post">推送数据</option>
							<option value="update">更新数据</option>
							<option value="del">删除数据</option>
						</select>
					</div>
				</div>
				<div class="form-group  form-group-lg">
					<div class="col-sm-8 col-sm-offset-2">
						<input type="tel" class="form-control" id="site" name="site" placeholder="要推送内容的网站,例如:www.example.com" required >
					</div>
				</div>
				<div class="form-group  form-group-lg">
					<div class="col-sm-8 col-sm-offset-2">
						<input type="tel" class="form-control" id="token" name="token" placeholder="百度站长平台秘钥,例如:ZD4V6EK2QNpzwill" required >
					</div>
				</div>
				<div class="form-group  form-group-lg">
					<div class="col-sm-8 col-sm-offset-2">
						<textarea class="form-control" name="sendURL" rows="8" placeholder="网址之间要换行,例如:
http://www.example/abc.hml
http://www.example/bcd.html" ></textarea>
					</div>
				</div>
				<div class="form-group  form-group-lg">
					<div class="col-sm-8 col-sm-offset-2">
						<button type="button" class="btn btn-success btn-lg btn-block" onclick="ajaxSub()">推送</button>
					</div>
				</div>
				<h3>&copy; 2016 powered by <a href="http://willxue.top" target="_blank">willxue</a></h3>
			</form>
		
			<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
			<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
			<!-- Include all compiled plugins (below), or include individual files as needed -->
			<script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
			<script src="/static/layer/layer.js"></script>
			<script type="text/javascript">
				function ajaxSub(){
					$.post("/send", $("#form").serialize(), function(result){
						if (result.indexOf("Exception")>0) {
							layer.alert("请确认站点和token是否匹配",{title: "错误",icon:2});
						} else {
							var data = JSON.parse(result);
							if (result.indexOf("success")>0) {
								layer.alert("成功推送了:"+data.success+" 个<br/>今天还能推送:"+data.remain+" 个<br/>不是本站而未处理的url列表: "+data.not_same_site+"<br/>不合法的url:"+data.not_valid,{icon:1});
							} else{
								layer.alert("推送失败了,错误码:"+data.error+"<br/>错误描述:"+data.message,{title: "错误",icon:2});
							}
						}
					});
				}
			</script>
		</div>
	</body>
</html>

Demo

在线demo部署在daocloud http://gobaidu.daoapp.io/