Go Backstage Project Combat

Source: Internet
Author: User

This project uses native development completely, does not use any web framework (such as: Gin,beego,martini, etc.), and ORM (such as: Gorm,xorm,beego)

Three-tier architecture

The three-tier architecture (3-tier architecture) typically has a three-tier architecture that divides the entire business application into: the interface layer (User Interface layer), the business logic layer, the data access layer Access layer). The purpose of distinguishing hierarchy is to think of "high cohesion and low coupling". In the design of software architecture, layered structure is the most common and most important structure.

Control Layer/Interface layer

Because I do not have a Web page in my project, so take the control layer, it is to upload your request from the page to the background code

Service Layer/Business logic layer

For the operation of the specific problem, it can also be said that the operation of the data layer, the data business logic processing. (The key is to abstract logical data from raw data) to provide all the functionality at the INTERFACE\API level. , the actual purpose of the "intermediary business layer" is to combine the most basic storage logic of the "Data Access layer" to form a business rule.

Persistent layer/data access layer

This layer of transactions directly manipulate the database, for data additions, deletions, modifications, lookups and so on. (The key is the granularity of the grasp) to ensure that the "Data access layer" in the function of the atomic nature! That is, the minimum and no further points. The data access layer is responsible for storing or reading the data.

Controller Combo Package

Controller "base class" encapsulation, mainly provides a method to save the file, mainly for Form-data request

Import ("io" "Mime/multipart" "net/http" "path") constbase_image_address = "./img/" Typecontrollerstruct{datainterface {}}typefileinfotostruct{//Image ID--idint64//thumbnail path is not used temporarily--the path of the database is not saved with compresspathstring//original path pathstring// Original file name originalfilenamestring//store file name such as: uuidutilfilenamestring//file size filesizeint64}//Get the number of uploaded files func (P *controller) Getfilenum (R *http. Request,keys. String) Int{m: = R.MULTIPARTFORMIFM ==nil{return0}iflen (keys) ==0{varnumintfor_,fileheaders: =rangem. File {num +=len (fileheaders)}returnnum}else{varnumintfor_,value: =rangekeys {num +=len (M.file[value])}returnnum}}// Parse the file in Form-data, if not the keys, regardless of the file name (filename) is uploaded, will be resolved, otherwise only the keys specified by the file func (P *controller) savefiles (R *http. Request,,relativepathstring,keys. String) []*fileinfoto{r.parsemultipartform (32<<20) m: = R. MULTIPARTFORMIFM ==nil{log. Println ("Not multipartfrom!") Returnnil}fileinfos: =make ([]*fileinfoto,0) FilePath: = base_image_address + relativepathfileutil.makedir (filePath) Iflen (keys) ==0{for_,fileheaders: =rangem. File {//traverse all of the field names (filename) to get Fileheadersfor_,fileheader: =rangefileheaders{to: = P.savefile (Filepath,relativepath, Fileheader) Fileinfos =append (fileinfos,to)}}}else{for_,value: =rangekeys {fileheaders: = m.File[value]// Gets fileheadersfor_,fileheader based on the field name (filename) specified when uploading the file: =rangefileheaders{to: = P.savefile (Filepath,relativepath, Fileheader) Fileinfos =append (fileinfos,to)}}}returnfileinfos}//save a single file func (P *controller) saveFile (FilePath, Relativepathstring,fileheader *multipart. Fileheader) *fileinfoto{file,err: = Fileheader.open () iferr!=nil{log. PRINTLN (Err) returnnil}deferfile. Close () Name,err: = Uuidutil. Randomuuid () Iferr!=nil{log. PRINTLN (err) Returnnil}filetype: = Fileutil. EXT (Fileheader.filename, ". jpg") NewName: = name + Filetypedst,err: = os. Create (FilePath + newName) Iferr!=nil{log. PRINTLN (Err) returnnil}deferdst. Close () Filesize,err: = Io. Copy (dst,file) Iferr!=nil{log. PRINTLN (Err) Returnnil}return&fileinfoto{path:relativepath + newname,originalfilename:fileheader.filename, Filename:newname,fIlesize:filesize}} 
fileutilimport("os""path")//创建多级目录funcMkDirAll(pathstring)bool{err := os.MkdirAll(path, os.ModePerm)iferr !=nil{returnfalse}returntrue}//检测文件夹或文件是否存在funcExist(filestring)bool{if_,err := os.Stat(file);os.IsNotExist(err){returnfalse}returntrue}//获取文件的类型,如:.jpg//如果获取不到,返回默认类型defaultExtfuncExt(fileNamestring,defaultExtstring)string{t := path.Ext(fileName)iflen(t) ==0{returndefaultExt}returnt}/// 检验文件夹是否存在,不存在 就创建funcMakeDir(filePathstring){if!Exist(filePath) {MkDirAll(filePath)}}//删除文件funcRemove(namestring)bool{err := os.Remove(name)iferr !=nil{returnfalse}returntrue}
uuidtuilimport("encoding/base64""math/rand")funcRandomUUID()(string,error){b :=make([]byte,32)if_,err := rand.Read(b);err !=nil{return"",err}returnbase64.URLEncoding.EncodeToString(b),nil}

Apicontroller is mainly used for the user system of a login status of information acquisition, according to the session in the request to obtain the user information stored on the server, if your background sub-user system and management end user system, and these two user systems are stored in two tables, You can also define a Backcontroller

typeApiControllerstruct{Controller}func (p *ApiController) GetUserId(w http.ResponseWriter,r *http.Request) uint{user := p.GetUser(w,r)ifuser ==nil{return0}returnuser.ID}func (p *ApiController) GetUser(w http.ResponseWriter,r *http.Request) *entity.User{session := GlobalSession().SessionStart(w,r)ifsession ==nil{returnnil}key_user := session.Get(constant.KEY_USER)ifuser,ok := key_user.(*entity.User);ok{returnuser}returnnil}

Database

Implementation of the persistence layer: https://blog.csdn.net/cj_286/article/details/80363796

http

Implementation of HTTP Server: https://blog.csdn.net/cj_286/article/details/80256988

Router

The implementation of route processing, in fact, is a forwarding function

type RouterHandler struct {}varmux = make(map[string]func(http.ResponseWriter,*http.Request))func (p *RouterHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {fmt.Println(r.URL.Path)iffun, ok := mux[r.URL.Path]; ok {fun(w, r)return}//静态资源ifstrings.HasPrefix(r.URL.Path,constant.STATIC_BAES_PATH){iffun, ok := mux[constant.STATIC_BAES_PATH]; ok {fun(w, r)return}}http.Error(w,"error URL:"+r.URL.String(), http.StatusBadRequest)}func (p *RouterHandler) Router(relativePath string, handler func(http.ResponseWriter, *http.Request)) {mux[relativePath] = handler}

Session

If there is login function, so need to use the session to remember the user's state, the following is the session technology implementation of the main type and interface definition, (excerpt: https://github.com/astaxie/ BUILD-WEB-APPLICATION-WITH-GOLANG/BLOB/MASTER/ZH/06.0.MD), the session expiration time can be set by itself, if set to one hour, the session will expire in one hour after the stop. The session will be automatically deleted, if the reply is kept within an hour can be accessed, the session will not expire

//主要用于session的管理,过期处理等type Manager struct {cookieName stringlock sync.Mutexprovider ProvidermaxLifeTime int64}//用于提供session存储方式的一个接口标准,可以用于提供session储存在内存、文件、数据库等方式type Provider interface {SessionInit(sid string)(Session,error)SessionRead(sid string)(Session,error)SessionDestroy(sid string) errorSessionGC(maxLifeTime int64)}//用于对session一些基本操作的定义type Session interface {Set(key, value interface{}) errorGet(key interface{}) interface{}Delete(key interface{}) errorSessionID()string}

Static resources

HTTP is required for static resource processing. Fileserver and Http.stripprefix functions, http.fileserver is usually used in conjunction with Http.stripprefix to use the Http.stripprefix function, which is to direct the request to the request processing that you specify through the parameters, before the specific The prefix is filtered out of the URL. Here is an example of a browser or HTTP client requesting a resource:

/static/example.png

The Stripprefix function will filter out the/static/and direct the modified request to HTTP. Fileserver the returned handler, so the requested resource will be:

/example.png

http. The handler returned by Fileserver will be looked up and the contents related to the folder or file system will be returned to you as a parameter (here you will "static" as the root directory of the static file). Because your "example.txt" file is in a static directory, you must define a relative path to get the correct file path.

Customize access paths as needed

http.Handle("/tmpfiles/",http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))

Fileserver has defined the root directory of the static file in "/tmp", but we want the URL to start with "/tmpfiles/". If someone requests "/tempfiles/example.txt", we want the server to send the file to him. To achieve this, we must filter out "/tmpfiles" from the URL, while the remaining path is relative to the root directory "/tmp". If we follow the above approach, we will get the following results:

/tmp/example.png

Demonstrate

A rough design of several APIs, the following is the access to the API request and response, the following in addition to registration and login will not detect the session, the other API will be detected, require login to be accessible.

Imageimageimageimage

Call to add comment feedback interface when not logged in status

Image

Login status Call Add Feedback interface

Image

accessing Static resources

Image

Project Address: Https://github.com/xiaojinwei/cgo

Reference: https://studygolang.com/articles/9197

Https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/06.0.md

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.