golang实战--实现短地址服务

golang写的简单的短地址服务,只做练手用,还有很多不完善的地方

TODO:

验证URL的有效性;

确认URL的协议(http、https)

数据库操作优化

现在的路由太简单了


下面贴上代码

package main

import (
	"database/sql"
	"fmt"
	"net/http"
	"io/ioutil"
	"encoding/json"
	_ "github.com/go-sql-driver/mysql"
)

var elements = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
var db *sql.DB

type returnData struct {
	ShortUrl string
	LongUrl string
}

//这里首字母一定要大写
//json数据与struct字段相匹配时,会查找与json中key相同的可导出字段(首字母大写)
type postData struct {
	LongUrl string
}

func main()  {
	Init()
	http.HandleFunc("/", simpleRoute)
	err := http.ListenAndServe(":9090", nil)
	if err != nil {
		panic(err)
	}
}

func Init()  {
	db, _ = sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/shortener")
	//defer db.Close()
}

//十进制转换成62进制
func base10ToBase62(n int64) string {
	var str string
	for n != 0 {
		str += string(elements[n % 62])
		n /= 62
	}

	for len(str) != 5 {
		str += "0"
	}
	return str
}

func buildResponse(p postData) returnData {
	stmtIns, err := db.Prepare("INSERT INTO urls VALUES (null, '', ?, 0)")
	if err != nil {
		panic(err.Error())
	}
	defer stmtIns.Close()

	result, err := stmtIns.Exec(p.LongUrl)
	if err != nil {
		panic(err.Error())
	}
	id, _ := result.LastInsertId()
	shorter := base10ToBase62(id)

	stmtUps, err := db.Prepare("UPDATE urls SET short_url=? WHERE id=?")
	if err != nil {
		panic(err.Error())
	}
	defer stmtUps.Close()

	stmtUps.Exec(shorter, id)

	var returns returnData
	returns.LongUrl = p.LongUrl
	returns.ShortUrl = shorter
	return  returns
}

func shortUri(w http.ResponseWriter, r *http.Request)  {
	defer r.Body.Close()
	var p postData
	data, _ := ioutil.ReadAll(r.Body)
	json.Unmarshal(data, &p)
	returnData := buildResponse(p)
	returnData.ShortUrl = "http://" + r.Host + "/"+ returnData.ShortUrl
	jsonData, err := json.Marshal(returnData)
	if err != nil {
		fmt.Println("json error:", err)
	}
	w.Write([]byte(jsonData))
}

func simpleRoute(w http.ResponseWriter, r *http.Request)  {
	urlPath := r.URL.Path
	if len(urlPath) == 6 {
		redirectUrl(w, r)
	} else if urlPath == "/shortener" {
		shortUri(w, r)
	} else {
		w.WriteHeader(404)
	}
}

func redirectUrl(w http.ResponseWriter, r *http.Request)  {
	urlPath := r.URL.Path
	rs := []rune(urlPath)
	urlPath = string(rs[1:])
	stmtOut, err := db.Prepare("SELECT long_url FROM urls WHERE short_url=?")
	if err != nil {
		panic(err.Error())
	}
	defer stmtOut.Close()

	var url string
	err = stmtOut.QueryRow(urlPath).Scan(&url)
	if err != nil {
		panic(err.Error())
	}
	http.Redirect(w, r, "http://" + url, 301)
}






你可能感兴趣的:(golang)