用Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)實(shí)現(xiàn)Web服務(wù)之項(xiàng)目介紹
我們將要?jiǎng)?chuàng)建一個(gè)什么項(xiàng)目呢?
我們要?jiǎng)?chuàng)建的項(xiàng)目是一個(gè)EBook電子書(shū)平臺(tái),接受用戶(hù)注冊(cè)登錄瀏覽圖書(shū),用戶(hù)可以購(gòu)買(mǎi)圖書(shū),系統(tǒng)自動(dòng)將電子書(shū)(pdf、epub 等格式電子書(shū))發(fā)送到用戶(hù)郵箱。這就是整個(gè)系統(tǒng)主線(xiàn)任務(wù)。
當(dāng)然整個(gè)項(xiàng)目不是一蹴而就馬上編寫(xiě)完成,而是分階段實(shí)現(xiàn),每個(gè)階段都有不同技術(shù)棧,像一個(gè)真實(shí)項(xiàng)目一樣迭代開(kāi)發(fā)。
用戶(hù)可以瀏覽平臺(tái)所有電子書(shū),管理員可以對(duì)圖書(shū)進(jìn)行CRUD操作。
在第一階段,我將使用Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)實(shí)現(xiàn)單表CRUD API 接口。
在這一個(gè)階段先創(chuàng)建一個(gè)電子書(shū)表book
,使用 MySQL 5.7版本 先維護(hù)好book表的功能,繼而迭代開(kāi)發(fā);建庫(kù)建表 SQL 語(yǔ)句如下:
CREATE DATABASE db_ebook; USE db_ebook; CREATE TABLE book ( id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '主鍵', isbn VARCHAR(13) NOT NULL COMMENT '國(guó)際標(biāo)準(zhǔn)書(shū)號(hào)', title VARCHAR(255) NOT NULL COMMENT '圖書(shū)名字', poster VARCHAR(255) NOT NULL COMMENT '圖書(shū)封面圖地址', pages INT UNSIGNED NOT NULL COMMENT '總頁(yè)數(shù)', price DECIMAL(6, 2) UNSIGNED COMMENT '圖書(shū)單價(jià)', published_at DATE NOT NULL COMMENT '發(fā)售日期', created_at TIMESTAMP NOT NULL default NOW() COMMENT '創(chuàng)建時(shí)間', updated_at TIMESTAMP NOT NULL default NOW() COMMENT '更新時(shí)間', unique index unq_isbn(`isbn`) ) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT '圖書(shū)表';
項(xiàng)目目錄結(jié)構(gòu)組織
在這一步,我將設(shè)計(jì)一個(gè)簡(jiǎn)潔實(shí)用的代碼組織架構(gòu),符合Go語(yǔ)言哲學(xué)思想,所見(jiàn)即所得。
初始化項(xiàng)目,使用 Go Module 開(kāi)發(fā);
mkdir -p $GOPATH/src/github.com/lightsaid/ebook cd $GOPATH/src/github.com/lightsaid/ebook go mod init github.com/lightsaid/ebook code .
目錄結(jié)構(gòu)
├── configs 配置文件,可以有多個(gè),例如開(kāi)發(fā)/生產(chǎn)環(huán)境配置 │ └── app.json ├── go.mod ├── go.sum ├── internal 系統(tǒng)內(nèi)部邏輯在此處實(shí)現(xiàn) │ ├── app app 要實(shí)現(xiàn)的api應(yīng)用程序 │ ├── config 加載配置 │ ├── dbrepo 數(shù)據(jù)庫(kù)操作 │ └── models 實(shí)體模型 ├── main.go 入口函數(shù) ├── pkg 公共模塊,可以提供給其他項(xiàng)目使用的模塊 │ └── logger 日志庫(kù) └── schema.sql
在Go中,internal
目錄是本項(xiàng)目?jī)?nèi)部代碼,不提供給其他項(xiàng)目使用,而且不管internal嵌套在一級(jí)、二級(jí)、三級(jí)...都是同樣不允許外部項(xiàng)目訪(fǎng)問(wèn);Go在編譯的時(shí)候做了區(qū)分。如果你想詳細(xì)了解Go如何組織代碼可以參考這個(gè)項(xiàng)目 project-layout
在上面其中pkg
目錄是存放公共模塊代碼,如核心業(yè)務(wù)沒(méi)有太多聯(lián)系輔助模塊,它可以提供給其他項(xiàng)目使用,盡管其他項(xiàng)目也不會(huì)用到??。
在這一階段,先來(lái)熱身一下,先編寫(xiě)簡(jiǎn)單的 logger 日志輸出功能和加載配置功能。 好在這一部分先介紹到這么多,下一節(jié)將開(kāi)始編碼。
logger/logger.go
package logger import ( "log" "os" ) var InfoLog *log.Logger var ErrorfoLog *log.Logger func SetGlobalLogger() { InfoLog = log.New(os.Stdout, "[INFO]\t", log.Ldate|log.Ltime) ErrorfoLog = log.New(os.Stdout, "[ERROR]\t", log.Ldate|log.Ltime|log.Lshortfile) }
上面創(chuàng)建兩個(gè)log實(shí)例,并配置日志輸出前綴,和日期文件名等信息
app.json (端口根據(jù)自己實(shí)際配置)
{ "env": "dev", "port": 9527, "dsn": "root:rootcc@tcp(127.0.0.1:3318)/db_ebook?charset=utf8mb4&parseTime=True", "maxOpenConns": 30, "maxIdleConns": 15, "maxIdleTime": "5m" }
config/config.go
package config import ( "encoding/json" "fmt" "os" "time" "github.com/lightsaid/ebook/pkg/logger" ) // AppConfig 應(yīng)用程序配置 type AppConfig struct { Env string `json:"env"` // 環(huán)境參數(shù):dev | prod Port int `json:"port"` // 服務(wù)端口 DSN string `json:"dsn"` // 數(shù)據(jù)庫(kù)鏈接 MaxOpenConns int `json:"maxOpenConns"` // 數(shù)據(jù)庫(kù)最大鏈接數(shù) MaxIdleConns int `json:"maxIdleConns"` // 數(shù)據(jù)庫(kù)鏈接最大空閑數(shù) MaxIdleTime string `json:"maxIdleTime"` // 數(shù)據(jù)庫(kù)鏈接最大空閑時(shí)間 } // MaxIdleTimeToDuration 將 MaxIdleTime 轉(zhuǎn)換成 time.Duration 返回,如果轉(zhuǎn)換出錯(cuò),返回默認(rèn)值 func (app *AppConfig) MaxIdleTimeToDuration() time.Duration { dur, err := time.ParseDuration(app.MaxIdleTime) if err != nil { logger.ErrorfoLog.Println("time.ParseDuration(app.MaxIdleTime) failed: " + err.Error()) return time.Minute * 5 } return dur } // LoadAppConfig 根據(jù)配置文件路徑加載配置 func LoadAppConfig(path string) (cfg AppConfig, err error) { var buf []byte buf, err = os.ReadFile(path) if err != nil { return } if err = json.Unmarshal(buf, &cfg); err != nil { return } return } func (a *AppConfig) Println() { if a.Env == "dev" { buf, _ := json.MarshalIndent(a, "", " ") fmt.Println(string(buf)) } }
在上面創(chuàng)建一個(gè)AppConfig
結(jié)構(gòu)體,并綁定json tag
,這樣json.Unmarshal
才能解碼。 在 Println 方法中 json.MarshalIndent
是格式化輸出json函數(shù)。上面格式輸出如圖:
這部分內(nèi)容分享到這里,下一節(jié)將初始化App路由。
到此這篇關(guān)于用Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)實(shí)現(xiàn)Web服務(wù)之項(xiàng)目介紹的文章就介紹到這了,更多相關(guān)Go語(yǔ)言標(biāo)準(zhǔn)庫(kù) 實(shí)現(xiàn)Web服務(wù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
go語(yǔ)言實(shí)現(xiàn)sftp包上傳文件和文件夾到遠(yuǎn)程服務(wù)器操作
這篇文章主要介紹了go語(yǔ)言實(shí)現(xiàn)sftp包上傳文件和文件夾到遠(yuǎn)程服務(wù)器操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12Golang使用Channel組建高并發(fā)HTTP服務(wù)器
Golang 作為一門(mén)高效的語(yǔ)言,在網(wǎng)絡(luò)編程方面表現(xiàn)也非常出色,這篇文章主要介紹了如何使用 Golang 和 Channel 組建高并發(fā) HTTP 服務(wù)器,感興趣的可以了解一下2023-06-06go語(yǔ)言yaml轉(zhuǎn)map、map遍歷的實(shí)現(xiàn)
本文主要介紹了go語(yǔ)言yaml轉(zhuǎn)map、map遍歷的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09