Iris introduction
Iris is a framework used to develop web applications in Go language. The framework supports writing once and running with minimum machine power anywhere, such as Android, ios, Linux and Windows. The framework only needs an executable service to run on the platform.
Iris framework is familiar to developers with its simple and powerful api. Iris not only provides developers with very simple access, but also supports MVC. In addition, it is easy to build micro services with iris.
On the official website of iris framework, it is known as the fastest Go back-end development framework. On iris's website document, some features and framework features of the framework are listed as follows:
Iris characteristics
- Focus on high performance
- Simple and fluent API
- High scalability
- Powerful routing and middleware ecosystem
- Building restful APIs using iris's unique expressionist path interpreter
- Dynamic path parameterization or wildcard routing does not conflict with static routing
- Use the redirect option to remove trailing slashes from the URL
- It's easy to use virtual hosts and subdomains
- Grouping API s and static or even dynamic subdomains
- net / http and Negroni like handlers via iris Fromstd compatible
- Define the processing function for any Http request error
- Support transaction and rollback
- Support response caching
- Use simple functions to embed resources and be compatible with go bindata
- mvc
- context
- Highly scalable rendering (currently supports markdown,json,xml, JSON, etc.)
- Text binder and convenient function of sending HTTP response
- Limit request body
- Provide static resources or embedded assets
- Localize i18N
- Compression (Gzip is built-in)
- Authentication
- Basic Authentication
- OAuth, OAuth2 (support more than 27 popular websites)
- JWT * server
- When providing services through TLS, automatically install and provide services from https://letsencrypt.org Certificate of
- The default is off
- Register on shutdown, error, or interrupt events
- Connect multiple servers, fully compatible with net / HTTP #
- View system Five templates are supported, which are implicitly and fully compatible with html/template
- Websocket library, whose API is similar to http://socket.io [you can still use your favorite if you like]
- Hot restart
- Typescript integration + Web IDE
Official source code address: https://github.com/kataras/iris
Iris web microservice framework example
Overall function
- Integrated aiwutech FileLogger logs are cut by day and output to different log files by level
- Integrated redis
- Integrating mysql
- Read etcd configuration
- Exception handling, global exception handling
- Interceptor print request and response parameters
- Front end html integration
- wait
Download iris dependency package
go get -u github.com/kataras/iris
main.go project entrance
init method: initialize relevant configurations, with notes
main method: start Iris service
package main import ( . "web-demo/config" . "web-demo/log" . "web-demo/redis" . "web-demo/db" _ "web-demo/handler" "web-demo/web" "flag" "fmt" "time" ) var showVersion = flag.Bool("v", true, "print version") func init(){ //Call flag Parse() flag.Parse() //Initialize profile ConfigRead() //Initialize log LogInit() //Initialize redis RedisInit(Cfg.RedisAddr,0 , Cfg.RedisPassword, Cfg.RedisMaxConn) //Initialize mysql SqlDBInit(&SqlDBParam{Cfg.MysqlHost, Cfg.MysqlPort, Cfg.MysqlUser, Cfg.MysqlPwd, Cfg.MysqlDb}) } func main() { if *showVersion { //This date is a date written dead. If you don't know this date, you can't format it correctly //It is said to be the day of the birth of go version := fmt.Sprintf("%s %s@%s", "web-demo", "1.0", time.Now().Format("2006-01-02 15:04:05")) fmt.Println(version) } Log.Info("start server...") //Listening port Log.Info("listen on :%s", Cfg.ListenPort) web.RunIris(Cfg.ListenPort) }
AccessLogMiddleware.go middleware interceptor
Add request header in interceptor
Print the request parameters and response parameters to the log file
package web import ( . "web-demo/util/threadlocal" . "web-demo/log" "github.com/kataras/iris" . "github.com/jtolds/gls" "strconv" "time" ) func init() { RegisterPreMiddleware(accessLogMiddleware{}) } type accessLogMiddleware struct { // your 'stateless' fields here } func (m accessLogMiddleware) Serve(ctx *iris.Context) { //check header //request id requestId := ctx.RequestHeader("X-Web-Demo-RequestId") if requestId == "" { requestId = strconv.FormatInt(time.Now().UnixNano(), 10) } //access log AccessLog.Info(requestId + "\t" + ctx.RequestIP() + "\t" + string(ctx.RequestURI())) //response requestId ctx.Response.Header.Add("X-Web-Demo-RequestId", requestId) //do chian Mgr.SetValues(Values{Rid: requestId}, func() { ctx.Next() }) //rrlog RRLog.Info(requestId + "\t" + "-RequestIP:==" + ctx.RequestIP()) RRLog.Info(requestId + "\t" + "-RequestP:==" + string(ctx.RequestPath(true))) RRLog.Info(requestId + "\t" + "-RequestD:==" + string(ctx.Request.Body())) RRLog.Info(requestId + "\t" + "-Response:==" + string(ctx.Response.Body())) }
logger.go log definition and configuration
package log import ( "flag" "github.com/aiwuTech/fileLogger" "os" . "web-demo/util/threadlocal" "web-demo/config" ) var Log Logger var ErrorLog Logger var AccessLog Logger var RRLog Logger var InnerRRLog Logger type Logger interface { Trace(format string, params ...interface{}) Info(format string, params ...interface{}) Warn(format string, params ...interface{}) Error(format string, params ...interface{}) } type CustomedLogger struct{ MyLogger Logger } func (cl CustomedLogger)Trace(format string, params ...interface{}){ cl.MyLogger.Trace(cl.resetFormat(format), params) } func (cl CustomedLogger)Info(format string, params ...interface{}){ cl.MyLogger.Info(cl.resetFormat(format), params) } func (cl CustomedLogger)Warn(format string, params ...interface{}){ cl.MyLogger.Warn(cl.resetFormat(format), params) } func (cl CustomedLogger)Error(format string, params ...interface{}){ cl.MyLogger.Error(cl.resetFormat(format), params) } func (cl CustomedLogger)resetFormat(format string) string{ logstr := format if rid, ok := Mgr.GetValue(Rid); ok { logstr = rid.(string) + " - " + logstr } return logstr } func LogInit() { logPath := config.Cfg.LogPath if (len(logPath) == 0) { logPath = "/Users/liang/ideaWorkspace/go/src/web-demo/logs/web-demo" } flag.Parse() if !isExist(logPath) { os.Mkdir(logPath, 0755) } logger := fileLogger.NewDailyLogger(logPath, "root.log", "", fileLogger.DEFAULT_LOG_SCAN, fileLogger.DEFAULT_LOG_SEQ) Log = CustomedLogger{MyLogger: logger} errorLog := fileLogger.NewDailyLogger(logPath, "error.log", "", fileLogger.DEFAULT_LOG_SCAN, fileLogger.DEFAULT_LOG_SEQ) ErrorLog = CustomedLogger{MyLogger: errorLog} accessLog := fileLogger.NewDailyLogger(logPath, "access.log", "", fileLogger.DEFAULT_LOG_SCAN, fileLogger.DEFAULT_LOG_SEQ) AccessLog = CustomedLogger{MyLogger: accessLog} rRLog := fileLogger.NewDailyLogger(logPath, "rr.log", "", fileLogger.DEFAULT_LOG_SCAN, fileLogger.DEFAULT_LOG_SEQ) RRLog = CustomedLogger{MyLogger: rRLog} innerRRLog := fileLogger.NewDailyLogger(logPath, "inner_rr.log", "", fileLogger.DEFAULT_LOG_SCAN, fileLogger.DEFAULT_LOG_SEQ) InnerRRLog = CustomedLogger{MyLogger: innerRRLog} } func isExist(path string) bool { _, err := os.Stat(path) return err == nil || os.IsExist(err) }
mysql.go mysql initialization connection
package db import ( . "web-demo/log" "fmt" _ "github.com/go-sql-driver/mysql" "github.com/jinzhu/gorm" . "web-demo/config" ) var Mysql *gorm.DB type SqlDBParam struct { Ip string Port int User string Pw string Database string } // mysql initialization file func SqlDBInit(param *SqlDBParam) { Log.Info("init mysql...") param_s := fmt.Sprintf( "%v:%v@tcp(%v:%v)/%v?parseTime=True&loc=Local", param.User, param.Pw, param.Ip, param.Port, param.Database, ) Log.Info("mysql param: %s", param_s) db, err := gorm.Open("mysql", param_s) if err != nil { Log.Error("open mysql error: %v", err) panic(err) } db.DB().SetMaxIdleConns(Cfg.MysqlMaxConn) db.SingularTable(true) db.LogMode(true) Mysql = db Log.Info("init mysql end.") }
redis.go redis initialization and common operation methods
package redis import ( . "web-demo/log" "github.com/garyburd/redigo/redis" "time" ) var ( redisPool *redis.Pool ) const ( maxIdle = 500 idleTimeout = 0 * time.Second wait = true ) //Init //eg: RedisInit("127.0.0.1:6379", 0, "pwd", 8) func RedisInit(server string, db int, password string, maxConn int) { maxActive := maxConn //Make a pool object redisPool = &redis.Pool{ // Maximum number of idle connections in the pool. MaxIdle: maxIdle, // Maximum number of connections allocated by the pool at a given time. // When zero, there is no limit on the number of connections in the pool. MaxActive: maxActive, // Close connections after remaining idle for this duration. If the value // is zero, then idle connections are not closed. Applications should set // the timeout to a value less than the server's timeout. IdleTimeout: idleTimeout, // If Wait is true and the pool is at the MaxActive limit, then Get() waits // for a connection to be returned to the pool before returning. Wait: wait, // Dial is an application supplied function for creating and configuring a // connection. // // The connection returned from Dial must not be in a special state // (subscribed to pubsub channel, transaction started, ...). Dial: func() (redis.Conn, error) { c, err := redis.Dial("tcp", server) if err != nil { return nil, err } if password != "" { if _, err := c.Do("AUTH", password); err != nil { c.Close() return nil, err } } if _, err := c.Do("SELECT", db); err != nil { c.Close() return nil, err } return c, nil }, // TestOnBorrow is an optional application supplied function for checking // the health of an idle connection before the connection is used again by // the application. Argument t is the time that the connection was returned // to the pool. If the function returns an error, then the connection is // closed. TestOnBorrow: func(c redis.Conn, t time.Time) error { if time.Since(t) < time.Minute { return nil } _, err := c.Do("PING") return err }, } Log.Info("redis[%v %v] init ok", server, db) } ......
Handler note that Iris will automatically scan the handler package name
If there are multiple packages, such as user and html in the demo, iris cannot be scanned at this time
You need to add a public file in the handler package to import the two packages, as shown below
package handler import ( _ "web-demo/handler/html" _ "web-demo/handler/user" )
Other functions will not be introduced in detail. Please see the source code
Web demo run
#Start project go run main.go #The following print indicates that port 8080 is successfully started listen on :8080
Browser access:
http://127.0.0.1:8080/webdemo/html/v1/passenger/login.md
Display login MD file content
http://127.0.0.1:8080/webdemo/html/v1/index
Display index HTML content
Demo source code address: https://github.com/golang-example/web-demo