租房項目 啓動前的處理

項目啓動

拆分原則

一、單一職責(一個服務只作一件事)html

二、服務粒度適中前端

三、考慮團隊結構mysql

四、以業務模型切入git

五、演進式拆分github

六、避免環形依賴和雙向依賴web

若是尚未安裝 beego 的話先安裝 beegoredis

$ go get -u -v github.com/astaxie/beego
$ go get -u -v github.com/beego/bee
$ cd $GOPATH/src/github.com/beego/bee
$ go build
$ sudo mv bee /bin/

服務發現的啓動

項目開始以前,咱們先要啓動咱們單機版的 consulsql

$ consul agent -dev

數據庫的準備

在 mysql 中建立一個數據庫:ihomeshell

$ mysql -uroot -p
# 輸入 root 密碼

# 建立1個數據庫:ihome
mysql>create database if not exists ihome default charset utf8 collate utf8_general_ci;

Web 端

能夠先去 Github 中提早查看一下 Web 端的文件結構::https://github.com/lpg-it/ihome/tree/master/ihomeWeb數據庫

建立命令

$ cd $GOPATH/src
$ micro new --type "web" ihome/ihomeWeb

Web 服務的調整

修改 main.go

package main

import (
        "github.com/julienschmidt/httprouter"
        "github.com/micro/go-log"
        "net/http"

        "github.com/micro/go-web"
)

func main() {
	// create new web service
	service := web.NewService(
		web.Name("go.micro.web.ihomeWeb"),
		web.Version("latest"),
		web.Address(":8080"),
	)

	// initialise service
	if err := service.Init(); err != nil {
		log.Fatal(err)
	}
	
	rou := httprouter.New()
	rou.NotFound = http.FileServer(http.Dir("html"))

	// register html handler
	service.Handle("/", rou)
	
	// run service
	if err := service.Run(); err != nil {
		log.Fatal(err)
	}
}

建立工具函數文件夾

# 建立工具函數文件夾
$ mkdir utils
# 進入文件夾建立文件
$ cd utils
# 配置文件讀取函數文件
$ sudo vim config.go
# 錯誤碼文件
$ sudo vim error.go
# 字符串拼接文件
$ sudo vim misc.go

配置 文件讀取文件 config.go

package utils

import (
	"github.com/astaxie/beego"
	//使用了beego框架的配置文件讀取模塊
	"github.com/astaxie/beego/config"
)

var (
	G_server_name  string //項目名稱
	G_server_addr  string //服務器ip地址
	G_server_port  string //服務器端口
	G_redis_addr   string //redis ip地址
	G_redis_port   string //redis port端口
	G_redis_dbnum  string //redis db 編號
	G_mysql_addr   string //mysql ip 地址
	G_mysql_port   string //mysql 端口
	G_mysql_dbname string //mysql db name
	G_fastdfs_port string //fastdfs 端口
	G_fastdfs_addr string //fastdfs ip
)

func InitConfig() {
	//從配置文件讀取配置信息
	//若是項目遷移須要進行修改
	appconf, err := config.NewConfig("ini", "/home/lpgit/go/src/ihome/ihomeWeb/conf/app.conf")
	if err != nil {
		beego.Debug(err)
		return
	}
	G_server_name = appconf.String("appname")
	G_server_addr = appconf.String("httpaddr")
	G_server_port = appconf.String("httpport")
	G_redis_addr = appconf.String("redisaddr")
	G_redis_port = appconf.String("redisport")
	G_redis_dbnum = appconf.String("redisdbnum")
	G_mysql_addr = appconf.String("mysqladdr")
	G_mysql_port = appconf.String("mysqlport")
	G_mysql_dbname = appconf.String("mysqldbname")
	G_fastdfs_port = appconf.String("fastdfsport")
	G_fastdfs_addr = appconf.String("fastdfsaddr")
	return
}

func init() {
	InitConfig()
}

錯誤碼文件 error.go

package utils

const (
	RECODE_OK         = "0"
	RECODE_DBERR      = "4001"
	RECODE_NODATA     = "4002"
	RECODE_DATAEXIST  = "4003"
	RECODE_DATAERR    = "4004"
	RECODE_SESSIONERR = "4101"
	RECODE_LOGINERR   = "4102"
	RECODE_PARAMERR   = "4103"
	RECODE_USERERR    = "4104"
	RECODE_ROLEERR    = "4105"
	RECODE_PWDERR     = "4106"
	RECODE_SMSERR     = "4017"
	RECODE_REQERR     = "4201"
	RECODE_IPERR      = "4202"
	RECODE_THIRDERR   = "4301"
	RECODE_IOERR      = "4302"
	RECODE_SERVERERR  = "4500"
	RECODE_UNKNOWERR  = "4501"
)

var recodeText = map[string]string{
	RECODE_OK:         "成功",
	RECODE_DBERR:      "數據庫查詢錯誤",
	RECODE_NODATA:     "無數據",
	RECODE_DATAEXIST:  "數據已存在",
	RECODE_DATAERR:    "數據錯誤",
	RECODE_SESSIONERR: "用戶未登陸",
	RECODE_LOGINERR:   "用戶登陸失敗",
	RECODE_PARAMERR:   "參數錯誤",
	RECODE_USERERR:    "用戶不存在或未激活",
	RECODE_ROLEERR:    "用戶身份錯誤",
	RECODE_PWDERR:     "密碼錯誤",
	RECODE_REQERR:     "非法請求或請求次數受限",
	RECODE_IPERR:      "IP受限",
	RECODE_THIRDERR:   "第三方系統錯誤",
	RECODE_IOERR:      "文件讀寫錯誤",
	RECODE_SERVERERR:  "內部錯誤",
	RECODE_UNKNOWERR:  "未知錯誤",
	RECODE_SMSERR:     "短信失敗",
}

func RecodeText(code string) string {
	str, ok := recodeText[code]
	if ok {
		return str
	}
	return recodeText[RECODE_UNKNOWERR]
}

字符串拼接文件 misc.go

package utils

/* 將url加上 http://IP:PROT/  前綴 */
//http:// + 127.0.0.1 + :+ 8080 + 請求

func AddDomain2Url(url string) (domain_url string) {
	domain_url = "http://" + G_fastdfs_addr + ":" + G_fastdfs_port + "/" + url

	return domain_url
}

建立數據庫文件

沒有下載 mysql 驅動的先下載 mysql

$ go get -u -v github.com/go-sql-driver/mysql
$ mkdir models
# 建立數據庫文件
$ sudo vim models.go

models.go 文件內容

package models

import (
	"github.com/astaxie/beego"
	// 使用了beego的orm模塊
	"github.com/astaxie/beego/orm"
	// go語言的sql的驅動
	_ "github.com/go-sql-driver/mysql"
	// 已經建立好的工具包
	"ihome/ihomeWeb/utils"
	"time"
)

/* 用戶 table_name = user */
type User struct {
	Id           int           `json:"user_id"`                       // 用戶編號
	Name         string        `orm:"size(32)"  json:"name"`          // 用戶暱稱
	PasswordHash string        `orm:"size(128)" json:"password"`      // 用戶密碼加密的
	Mobile       string        `orm:"size(11);unique"  json:"mobile"` // 手機號
	RealName     string        `orm:"size(32)" json:"real_name"`      // 真實姓名  實名認證
	IdCard       string        `orm:"size(20)" json:"id_card"`        // 身份證號  實名認證
	AvatarUrl    string        `orm:"size(256)" json:"avatar_url"`    // 用戶頭像路徑       經過 fastDFS 進行圖片存儲
	Houses       []*House      `orm:"reverse(many)" json:"houses"`    // 用戶發佈的房屋信息  一我的多套房
	Orders       []*OrderHouse `orm:"reverse(many)" json:"orders"`    // 用戶下的訂單       一我的屢次訂單
}

/* 房屋信息 table_name = house */
type House struct {
	Id            int           `json:"house_id"`                                          // 房屋編號
	User          *User         `orm:"rel(fk)" json:"user_id"`                             // 房屋主人的用戶編號  與用戶進行關聯
	Area          *Area         `orm:"rel(fk)" json:"area_id"`                             // 歸屬地的區域編號   和地區表進行關聯
	Title         string        `orm:"size(64)" json:"title"`                              // 房屋標題
	Price         int           `orm:"default(0)" json:"price"`                            // 單價,單位:分   每次的價格要乘以100
	Address       string        `orm:"size(512)" orm:"default('')" json:"address"`         // 地址
	RoomCount     int           `orm:"default(1)" json:"room_count"`                       // 房間數目
	Acreage       int           `orm:"default(0)" json:"acreage"`                          // 房屋總面積
	Unit          string        `orm:"size(32)" orm:"default('')" json:"unit"`             // 房屋單元,如 幾室幾廳
	Capacity      int           `orm:"default(1)" json:"capacity"`                         // 房屋容納的總人數
	Beds          string        `orm:"size(64)" orm:"default('')" json:"beds"`             // 房屋牀鋪的配置
	Deposit       int           `orm:"default(0)" json:"deposit"`                          // 押金
	MinDays       int           `orm:"default(1)" json:"min_days"`                         // 最少入住的天數
	MaxDays       int           `orm:"default(0)" json:"max_days"`                         // 最多入住的天數 0表示不限制
	OrderCount    int           `orm:"default(0)" json:"order_count"`                      // 預約完成的該房屋的訂單數
	IndexImageUrl string        `orm:"size(256)" orm:"default('')" json:"index_image_url"` // 房屋主圖片路徑
	Facilities    []*Facility   `orm:"reverse(many)" json:"facilities"`                    // 房屋設施   與設施表進行關聯
	Images        []*HouseImage `orm:"reverse(many)" json:"img_urls"`                      // 房屋的圖片   除主要圖片以外的其餘圖片地址
	Orders        []*OrderHouse `orm:"reverse(many)" json:"orders"`                        // 房屋的訂單    與房屋表進行管理
	Ctime         time.Time     `orm:"auto_now_add;type(datetime)" json:"ctime"`
}

// 首頁最高展現的房屋數量
var HomePageMaxHouses int = 5

// 房屋列表頁面每頁顯示條目數
var HouseListPageCapacity int = 2

// 處理房子信息
func (this *House) ToHouseInfo() interface{} {
	houseInfo := map[string]interface{}{
		"house_id":    this.Id,
		"title":       this.Title,
		"price":       this.Price,
		"area_name":   this.Area.Name,
		"img_url":     utils.AddDomain2Url(this.IndexImageUrl),
		"room_count":  this.RoomCount,
		"order_count": this.OrderCount,
		"address":     this.Address,
		"user_avatar": utils.AddDomain2Url(this.User.AvatarUrl),
		"ctime":       this.Ctime.Format("2006-01-02 15:04:05"),
	}

	return houseInfo
}

// 處理 1 個房子的所有信息
func (this *House) ToOneHouseDesc() interface{} {
	houseDesc := map[string]interface{}{
		"hid":         this.Id,
		"user_id":     this.User.Id,
		"user_name":   this.User.Name,
		"user_avatar": utils.AddDomain2Url(this.User.AvatarUrl),
		"title":       this.Title,
		"price":       this.Price,
		"address":     this.Address,
		"room_count":  this.RoomCount,
		"acreage":     this.Acreage,
		"unit":        this.Unit,
		"capacity":    this.Capacity,
		"beds":        this.Beds,
		"deposit":     this.Deposit,
		"min_days":    this.MinDays,
		"max_days":    this.MaxDays,
	}

	//房屋圖片
	imgUrls := []string{}
	for _, imgUrl := range this.Images {
		imgUrls = append(imgUrls, utils.AddDomain2Url(imgUrl.Url))
	}
	houseDesc["img_urls"] = imgUrls

	//房屋設施
	facilities := []int{}
	for _, facility := range this.Facilities {
		facilities = append(facilities, facility.Id)
	}
	houseDesc["facilities"] = facilities

	//評論信息

	comments := []interface{}{}
	orders := []OrderHouse{}
	o := orm.NewOrm()
	orderNum, err := o.QueryTable("order_house").Filter("house__id", this.Id).Filter("status", OrderStatusComplete).OrderBy("-ctime").Limit(10).All(&orders)
	if err != nil {
		beego.Error("select orders comments error, err =", err, "house id = ", this.Id)
	}
	for i := 0; i < int(orderNum); i++ {
		o.LoadRelated(&orders[i], "User")
		var username string
		if orders[i].User.Name == "" {
			username = "匿名用戶"
		} else {
			username = orders[i].User.Name
		}

		comment := map[string]string{
			"comment":   orders[i].Comment,
			"user_name": username,
			"ctime":     orders[i].Ctime.Format("2006-01-02 15:04:05"),
		}
		comments = append(comments, comment)
	}
	houseDesc["comments"] = comments

	return houseDesc
}

/* 區域信息 table_name = area */ //區域信息是須要咱們手動添加到數據庫中的
type Area struct {
	Id     int      `json:"aid"`                        // 區域編號     1    2
	Name   string   `orm:"size(32)" json:"aname"`       // 區域名字     昌平 海淀
	Houses []*House `orm:"reverse(many)" json:"houses"` // 區域全部的房屋   與房屋表進行關聯
}

/* 設施信息 table_name = "facility"*/ // 設施信息 須要咱們提早手動添加的
type Facility struct {
	Id     int      `json:"fid"`     // 設施編號
	Name   string   `orm:"size(32)"` // 設施名字
	Houses []*House `orm:"rel(m2m)"` // 都有哪些房屋有此設施  與房屋表進行關聯的
}

/* 房屋圖片 table_name = "house_image"*/
type HouseImage struct {
	Id    int    `json:"house_image_id"`         // 圖片 id
	Url   string `orm:"size(256)" json:"url"`    // 圖片 url     存放咱們房屋的圖片
	House *House `orm:"rel(fk)" json:"house_id"` // 圖片所屬房屋編號
}

const (
	OrderStatusWaitAccept  = "WAIT_ACCEPT"  //待接單
	OrderStatusWaitPayment = "WAIT_PAYMENT" //待支付
	OrderStatusPaid        = "PAID"         //已支付
	OrderStatusWaitComment = "WAIT_COMMENT" //待評價
	OrderStatusComplete    = "COMPLETE"     //已完成
	OrderStatusCanceled    = "CONCELED"     //已取消
	OrderStatusRejected    = "REJECTED"     //已拒單
)

/* 訂單 table_name = order */
type OrderHouse struct {
	Id         int       `json:"order_id"`               //訂單編號
	User       *User     `orm:"rel(fk)" json:"user_id"`  //下單的用戶編號   //與用戶表進行關聯
	House      *House    `orm:"rel(fk)" json:"house_id"` //預約的房間編號   //與房屋信息進行關聯
	BeginDate  time.Time `orm:"type(datetime)"`          //預約的起始時間
	EndDate    time.Time `orm:"type(datetime)"`          //預約的結束時間
	Days       int       //預約總天數
	HousePrice int       //房屋的單價
	Amount     int       //訂單總金額
	Status     string    `orm:"default(WAIT_ACCEPT)"`                 //訂單狀態
	Comment    string    `orm:"size(512)"`                            //訂單評論
	Ctime      time.Time `orm:"auto_now;type(datetime)" json:"ctime"` //每次更新此表,都會更新這個字段
	Credit     bool      //表示我的徵信狀況 true表示良好
}

// 處理訂單信息
func (this *OrderHouse) ToOrderInfo() interface{} {
	orderInfo := map[string]interface{}{
		"order_id":   this.Id,
		"title":      this.House.Title,
		"img_url":    utils.AddDomain2Url(this.House.IndexImageUrl),
		"start_date": this.BeginDate.Format("2006-01-02 15:04:05"),
		"end_date":   this.EndDate.Format("2006-01-02 15:04:05"),
		"ctime":      this.Ctime.Format("2006-01-02 15:04:05"),
		"days":       this.Days,
		"amount":     this.Amount,
		"status":     this.Status,
		"comment":    this.Comment,
		"credit":     this.Credit,
	}

	return orderInfo
}

// 數據庫的初始化
func init() {
	//調用什麼驅動
	orm.RegisterDriver("mysql", orm.DRMySQL)

	// set default database
	// 鏈接數據   ( 默認參數 ,mysql數據庫 ,"數據庫的用戶名 :數據庫密碼@tcp("+數據庫地址+":"+數據庫端口+")/庫名?格式",默認參數)
	orm.RegisterDataBase("default", "mysql", "root:lpg123456@tcp("+utils.G_mysql_addr+":"+utils.G_mysql_port+")/ihome?charset=utf8", 30)

	// 註冊 model 建表
	orm.RegisterModel(new(User), new(House), new(Area), new(Facility), new(HouseImage), new(OrderHouse))

	// create table
	//第一個是別名
	// 第二個是是否強制替換模塊   若是表變動就將false 換成true 以後再換回來表就便更好來了
	//第三個參數是若是沒有則同步或建立
	orm.RunSyncdb("default", false, true)
}

運行服務而且建立表單

# 建立 conf 文件夾用來存放配置文件
$ mkdir conf
# 建立data.sql文件
$ sudo vim data.sql

datat.sql 文件內容

INSERT INTO `area`(`name`) VALUES ('東城區'),('西城區'),('朝陽區'),('海淀區'),('昌平區'),('豐臺區'),('房山區'),('通州區'),('順義區'),('大興區'),('懷柔區'),('平谷區'),('密雲區'),('延慶區'),('石景山區');
INSERT INTO `facility`(`name`) VALUES('無線網絡'),('熱水淋浴'),('空調'),('暖氣'),('容許吸菸'),('飲水設備'),('牙具'),('香皂'),('拖鞋'),('手紙'),('毛巾'),('沐浴露、洗髮露'),('冰箱'),('洗衣機'),('電梯'),('容許作飯'),('容許帶寵物'),('容許聚會'),('門禁系統'),('停車位'),('有線網絡'),('電視'),('浴缸'),('吃雞'),('打檯球');

修改 main.go 內容

import (
	_ "ihome/ihomeWeb/models"
)

登陸 mysql 進行數據導入

# 登陸mysql
$ mysql -uroot -p
# 輸入root密碼
Mysql> use ihome;
# 數據的導入
mysql> source ./conf/data.sql;
# 數據檢查
mysql> select * from area;
mysql> select * from facility;

image.png

建立 app.conf文件

# 應用名稱
appname = ihome
# 地址
httpaddr = 127.0.0.1
# 端口
httpport = 8080
# 數據庫地址
mysqladdr = 127.0.0.1
# 數據庫端口
mysqlport = 3306

導入前端頁面

html 文件下載地址:https://cloud.189.cn/t/IzYbIbQVbEJn (訪問碼: 2owm)

運行

go run main.go

打開瀏覽器,輸入:127.0.0.1:8080,就能夠看到效果啦。

接下來, 我就帶領你們一步一步完成每一個服務。

李培冠博客

歡迎訪問個人我的網站:

李培冠博客:lpgit.com

相關文章
相關標籤/搜索