Browse Source

Added sync.Pool to go-std (#4526)

* deleted some go test; updated go vet to 1.12 in fasthttp, go-std, iris; added evio tests

* add sync.Pool to go-std

* test sync.Pool in DBHandler

* add some sync.Pool to go-std

* fixed fortunes test in go-std

* before merge

* added sync.Pool in go-std mysql and mgo drivers

* fix go ver in Go/iris

* fix num loops in Go/evio
chunariov 6 years ago
parent
commit
754ff319bd
30 changed files with 499 additions and 273 deletions
  1. 1 1
      frameworks/Go/evio/src/main.go
  2. 1 1
      frameworks/Go/go-std/go-mgo-prefork.dockerfile
  3. 1 1
      frameworks/Go/go-std/go-mgo.dockerfile
  4. 1 1
      frameworks/Go/go-std/go-my-prefork.dockerfile
  5. 1 1
      frameworks/Go/go-std/go-my.dockerfile
  6. 1 1
      frameworks/Go/go-std/go-pgx-easyjson.dockerfile
  7. 1 1
      frameworks/Go/go-std/go-pgx-prefork-easyjson.dockerfile
  8. 1 1
      frameworks/Go/go-std/go-pgx-prefork-quicktemplate.dockerfile
  9. 1 1
      frameworks/Go/go-std/go-pgx-prefork.dockerfile
  10. 1 1
      frameworks/Go/go-std/go-pgx-quicktemplate.dockerfile
  11. 1 1
      frameworks/Go/go-std/go-pgx.dockerfile
  12. 4 1
      frameworks/Go/go-std/src/go.mod
  13. 8 0
      frameworks/Go/go-std/src/go.sum
  14. 89 22
      frameworks/Go/go-std/src/handlers/handlers.go
  15. 52 12
      frameworks/Go/go-std/src/handlers/handlers_easyjson.go
  16. 14 0
      frameworks/Go/go-std/src/handlers/message.go
  17. 14 2
      frameworks/Go/go-std/src/main.go
  18. 15 11
      frameworks/Go/go-std/src/storage/db.go
  19. 15 10
      frameworks/Go/go-std/src/storage/mgo.go
  20. 42 30
      frameworks/Go/go-std/src/storage/mysql.go
  21. 49 29
      frameworks/Go/go-std/src/storage/pgx.go
  22. 138 138
      frameworks/Go/go-std/src/storage/pq.go
  23. 26 0
      frameworks/Go/go-std/src/storage/world.go
  24. 16 1
      frameworks/Go/go-std/src/templates/fortune.go
  25. 1 1
      frameworks/Go/iris/iris-pgx-prefork.dockerfile
  26. 1 1
      frameworks/Go/iris/iris-pgx-quicktemplate-prefork.dockerfile
  27. 1 1
      frameworks/Go/iris/iris-pgx-quicktemplate.dockerfile
  28. 1 1
      frameworks/Go/iris/iris-pgx.dockerfile
  29. 1 1
      frameworks/Go/iris/iris-prefork.dockerfile
  30. 1 1
      frameworks/Go/iris/iris.dockerfile

+ 1 - 1
frameworks/Go/evio/src/main.go

@@ -33,7 +33,7 @@ func main() {
 	flag.StringVar(&unixsocket, "unixsocket", "", "unix socket")
 	flag.IntVar(&port, "port", 8080, "server port")
 	flag.BoolVar(&stdlib, "stdlib", false, "use stdlib")
-	flag.IntVar(&loops, "loops", 0, "num loops")
+	flag.IntVar(&loops, "loops", -1, "num loops")
 	flag.Parse()
 
 	res = "Hello, World!"

+ 1 - 1
frameworks/Go/go-std/go-mgo-prefork.dockerfile

@@ -1,4 +1,4 @@
-FROM golang:1.11.5
+FROM golang:1.12
 
 ENV GO111MODULE on
 WORKDIR /go-std

+ 1 - 1
frameworks/Go/go-std/go-mgo.dockerfile

@@ -1,4 +1,4 @@
-FROM golang:1.11.5
+FROM golang:1.12
 
 ENV GO111MODULE on
 WORKDIR /go-std

+ 1 - 1
frameworks/Go/go-std/go-my-prefork.dockerfile

@@ -1,4 +1,4 @@
-FROM golang:1.11.5
+FROM golang:1.12
 
 ENV GO111MODULE on
 WORKDIR /go-std

+ 1 - 1
frameworks/Go/go-std/go-my.dockerfile

@@ -1,4 +1,4 @@
-FROM golang:1.11.5
+FROM golang:1.12
 
 ENV GO111MODULE on
 WORKDIR /go-std

+ 1 - 1
frameworks/Go/go-std/go-pgx-easyjson.dockerfile

@@ -1,4 +1,4 @@
-FROM golang:1.11.5
+FROM golang:1.12
 
 ENV GO111MODULE on
 WORKDIR /go-std

+ 1 - 1
frameworks/Go/go-std/go-pgx-prefork-easyjson.dockerfile

@@ -1,4 +1,4 @@
-FROM golang:1.11.5
+FROM golang:1.12
 
 ENV GO111MODULE on
 WORKDIR /go-std

+ 1 - 1
frameworks/Go/go-std/go-pgx-prefork-quicktemplate.dockerfile

@@ -1,4 +1,4 @@
-FROM golang:1.11.5
+FROM golang:1.12
 
 ENV GO111MODULE on
 WORKDIR /go-std

+ 1 - 1
frameworks/Go/go-std/go-pgx-prefork.dockerfile

@@ -1,4 +1,4 @@
-FROM golang:1.11.5
+FROM golang:1.12
 
 ENV GO111MODULE on
 WORKDIR /go-std

+ 1 - 1
frameworks/Go/go-std/go-pgx-quicktemplate.dockerfile

@@ -1,4 +1,4 @@
-FROM golang:1.11.5
+FROM golang:1.12
 
 ENV GO111MODULE on
 WORKDIR /go-std

+ 1 - 1
frameworks/Go/go-std/go-pgx.dockerfile

@@ -1,4 +1,4 @@
-FROM golang:1.11.5
+FROM golang:1.12
 
 ENV GO111MODULE on
 WORKDIR /go-std

+ 4 - 1
frameworks/Go/go-std/src/go.mod

@@ -6,12 +6,15 @@ require (
 	github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 // indirect
 	github.com/jackc/pgx v3.3.0+incompatible
 	github.com/kr/pretty v0.1.0 // indirect
-	github.com/lib/pq v1.0.0
+	github.com/lib/pq v1.0.0 // indirect
 	github.com/mailru/easyjson v0.0.0-20190221075403-6243d8e04c3f
 	github.com/pkg/errors v0.8.1 // indirect
 	github.com/satori/go.uuid v1.2.0 // indirect
 	github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 // indirect
+	github.com/valyala/bytebufferpool v1.0.0
 	github.com/valyala/quicktemplate v1.0.2
+	google.golang.org/appengine v1.4.0 // indirect
 	gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
 	gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce
+	gopkg.in/yaml.v2 v2.2.2 // indirect
 )

+ 8 - 0
frameworks/Go/go-std/src/go.sum

@@ -2,6 +2,7 @@ github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I
 github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
 github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
 github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 h1:vr3AYkKovP8uR8AvSGGUK1IDqRa5lAAvEkZG1LKaCRc=
 github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=
 github.com/jackc/pgx v3.3.0+incompatible h1:Wa90/+qsITBAPkAZjiByeIGHFcj3Ztu+VzrrIpHjL90=
@@ -28,7 +29,14 @@ github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyC
 github.com/valyala/fasthttp v0.0.0-20180905170723-c6fd90e432cc/go.mod h1:+g/po7GqyG5E+1CNgquiIxJnsXEi5vwFn5weFujbO78=
 github.com/valyala/quicktemplate v1.0.2 h1:ZeVRKan1W/25u5f9ilDo5HWtdxD+QxR10WrZwxqLM54=
 github.com/valyala/quicktemplate v1.0.2/go.mod h1:KZAB+RlYlfNtBUGQMzIrnE8uuNgD2SbUn5CpZyod0sk=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU=
 gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
+gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

+ 89 - 22
frameworks/Go/go-std/src/handlers/handlers.go

@@ -7,18 +7,12 @@ import (
 	"sort"
 	"strconv"
 
+	"github.com/valyala/bytebufferpool"
+
 	"go-std/src/storage"
 	"go-std/src/templates"
 )
 
-// var (
-// 	// Database
-// 	worldSelectPrepared   *sql.Stmt
-// 	worldUpdatePrepared   *sql.Stmt
-// 	fortuneSelectPrepared *sql.Stmt
-// 	maxConnections        = runtime.NumCPU()
-// )
-
 func queriesParam(r *http.Request) int {
 	q, err := strconv.Atoi(r.URL.Query().Get("queries"))
 	if err != nil || q < 1 {
@@ -31,43 +25,52 @@ func queriesParam(r *http.Request) int {
 
 // JSONHandler . Test 1: JSON serialization
 func JSONHandler(w http.ResponseWriter, r *http.Request) {
+	m := MessagePool.Get().(*Message)
+	m.Message = "Hello, World!"
 	w.Header().Set("Server", "Go")
 	w.Header().Set("Content-Type", "application/json")
-	json.NewEncoder(w).Encode(&Message{"Hello, World!"})
+	json.NewEncoder(w).Encode(m)
+	MessagePool.Put(m)
 }
 
 // DBHandler . Test 2: Single database query
 func DBHandler(db storage.DB) func(w http.ResponseWriter, r *http.Request) {
 	return func(w http.ResponseWriter, r *http.Request) {
-		world, err := db.GetOneRandomWorld()
-		if err != nil {
+		world := storage.WorldPool.Get().(*storage.World)
+
+		if err := db.GetOneRandomWorld(world); err != nil {
 			http.Error(w, err.Error(), http.StatusInternalServerError)
 			return
 		}
 
 		w.Header().Set("Server", "Go")
 		w.Header().Set("Content-Type", "application/json")
-		json.NewEncoder(w).Encode(&world)
+		json.NewEncoder(w).Encode(world)
+		storage.WorldPool.Put(world)
 	}
 }
 
 // QueriesHandler . Test 3: Multiple database queries
 func QueriesHandler(db storage.DB) func(w http.ResponseWriter, r *http.Request) {
 	return func(w http.ResponseWriter, r *http.Request) {
-		q := queriesParam(r)
-		results := make([]storage.World, q)
+		queries := queriesParam(r)
+
+		// worlds := make([]storage.World, queries)
+		worlds := storage.WorldsPool.Get().([]storage.World)[:queries]
 
 		var err error
-		for i := 0; i < q; i++ {
-			results[i], err = db.GetOneRandomWorld()
-			if err != nil {
+		for i := 0; i < queries; i++ {
+			if err = db.GetOneRandomWorld(&worlds[i]); err != nil {
 				log.Println(err)
 			}
 		}
 
 		w.Header().Set("Server", "Go")
 		w.Header().Set("Content-Type", "application/json")
-		json.NewEncoder(w).Encode(results)
+		json.NewEncoder(w).Encode(worlds)
+
+		worlds = worlds[:0]
+		storage.WorldsPool.Put(worlds)
 	}
 }
 
@@ -93,6 +96,30 @@ func FortuneHandler(db storage.DB) func(w http.ResponseWriter, r *http.Request)
 	}
 }
 
+// FortuneHandlerPool . Test 4: Fortunes
+func FortuneHandlerPool(db storage.DB) func(w http.ResponseWriter, r *http.Request) {
+	return func(w http.ResponseWriter, r *http.Request) {
+		fortunes, err := db.GetFortunesPool()
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+			return
+		}
+		fortunes = append(fortunes, templates.Fortune{Message: "Additional fortune added at request time."})
+
+		sort.Slice(fortunes, func(i, j int) bool {
+			return fortunes[i].Message < fortunes[j].Message
+		})
+
+		w.Header().Set("Server", "Go")
+		w.Header().Set("Content-Type", "text/html; charset=utf-8")
+		if err = templates.FortuneTemplate.Execute(w, fortunes); err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+		}
+		fortunes = fortunes[:0]
+		templates.FortunesPool.Put(fortunes)
+	}
+}
+
 // FortuneQuickHandler . Test 4: Fortunes
 func FortuneQuickHandler(db storage.DB) func(w http.ResponseWriter, r *http.Request) {
 	return func(w http.ResponseWriter, r *http.Request) {
@@ -113,13 +140,46 @@ func FortuneQuickHandler(db storage.DB) func(w http.ResponseWriter, r *http.Requ
 	}
 }
 
+// FortuneQuickHandlerPool . Test 4: Fortunes
+func FortuneQuickHandlerPool(db storage.DB) func(w http.ResponseWriter, r *http.Request) {
+	return func(w http.ResponseWriter, r *http.Request) {
+		fortunes, err := db.GetFortunesPool()
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+			return
+		}
+		fortunes = append(fortunes, templates.Fortune{Message: "Additional fortune added at request time."})
+
+		sort.Slice(fortunes, func(i, j int) bool {
+			return fortunes[i].Message < fortunes[j].Message
+		})
+
+		w.Header().Set("Server", "Go")
+		w.Header().Set("Content-Type", "text/html; charset=utf-8")
+		templates.WriteFortunePage(w, fortunes)
+
+		fortunes = fortunes[:0]
+		templates.FortunesPool.Put(fortunes)
+	}
+}
+
 // UpdateHandler . Test 5: Database updates
 func UpdateHandler(db storage.DB) func(w http.ResponseWriter, r *http.Request) {
 	return func(w http.ResponseWriter, r *http.Request) {
-		q := queriesParam(r)
+		queries := queriesParam(r)
+		var err error
 
-		worlds, err := db.UpdateRandomWorlds(q)
-		if err != nil {
+		// worlds := make([]storage.World, queries)
+		worlds := storage.WorldsPool.Get().([]storage.World)[:queries]
+
+		// for _, world := range worlds {
+		for i := 0; i < queries; i++ {
+			if err = db.GetOneRandomWorld(&worlds[i]); err != nil {
+				log.Println(err)
+			}
+		}
+
+		if err = db.UpdateWorlds(worlds, queries); err != nil {
 			log.Println(err)
 			return
 		}
@@ -127,6 +187,9 @@ func UpdateHandler(db storage.DB) func(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set("Server", "Go")
 		w.Header().Set("Content-Type", "application/json")
 		json.NewEncoder(w).Encode(worlds)
+
+		worlds = worlds[:0]
+		storage.WorldsPool.Put(worlds)
 	}
 }
 
@@ -134,5 +197,9 @@ func UpdateHandler(db storage.DB) func(w http.ResponseWriter, r *http.Request) {
 func PlaintextHandler(w http.ResponseWriter, r *http.Request) {
 	w.Header().Set("Server", "Go")
 	w.Header().Set("Content-Type", "text/plain")
-	w.Write([]byte("Hello, World!"))
+	b := bytebufferpool.Get()
+	b.SetString("Hello, World!")
+	w.Write(b.Bytes())
+	b.Reset()
+	bytebufferpool.Put(b)
 }

+ 52 - 12
frameworks/Go/go-std/src/handlers/handlers_easyjson.go

@@ -18,48 +18,88 @@ func JSONHandlerEasyJSON(w http.ResponseWriter, r *http.Request) {
 // DBHandlerEasyJSON . Test 2: Single database query
 func DBHandlerEasyJSON(db storage.DB) func(w http.ResponseWriter, r *http.Request) {
 	return func(w http.ResponseWriter, r *http.Request) {
-		world, err := db.GetOneRandomWorld()
-		if err != nil {
+		world := storage.WorldPool.Get().(*storage.World)
+		if err := db.GetOneRandomWorld(world); err != nil {
 			http.Error(w, err.Error(), http.StatusInternalServerError)
 			return
 		}
-
 		w.Header().Set("Server", "Go")
-		easyjson.MarshalToHTTPResponseWriter(&world, w)
+		easyjson.MarshalToHTTPResponseWriter(world, w)
+		storage.WorldPool.Put(world)
 	}
 }
 
+// // QueriesHandlerEasyJSON . Test 3: Multiple database queries
+// func QueriesHandlerEasyJSON(db storage.DB) func(w http.ResponseWriter, r *http.Request) {
+// 	return func(w http.ResponseWriter, r *http.Request) {
+// 		q := queriesParam(r)
+// 		worlds := make([]storage.World, q)
+// 		var err error
+// 		for i := 0; i < q; i++ {
+// 			worlds[i], err = db.GetOneRandomWorld()
+// 			if err != nil {
+// 				log.Println(err)
+// 			}
+// 		}
+// 		w.Header().Set("Server", "Go")
+// 		easyjson.MarshalToHTTPResponseWriter(storage.Worlds(worlds), w)
+// 	}
+// }
+
 // QueriesHandlerEasyJSON . Test 3: Multiple database queries
 func QueriesHandlerEasyJSON(db storage.DB) func(w http.ResponseWriter, r *http.Request) {
 	return func(w http.ResponseWriter, r *http.Request) {
-		q := queriesParam(r)
-		worlds := make([]storage.World, q)
+		queries := queriesParam(r)
+		worlds := storage.WorldsPool.Get().([]storage.World)[:queries]
 
 		var err error
-		for i := 0; i < q; i++ {
-			worlds[i], err = db.GetOneRandomWorld()
-			if err != nil {
+		for i := 0; i < queries; i++ {
+			if err = db.GetOneRandomWorld(&worlds[i]); err != nil {
 				log.Println(err)
 			}
 		}
 
 		w.Header().Set("Server", "Go")
 		easyjson.MarshalToHTTPResponseWriter(storage.Worlds(worlds), w)
+		worlds = worlds[:0]
+		storage.WorldsPool.Put(worlds)
 	}
 }
 
+// // UpdateHandlerEasyJSON . Test 5: Database updates
+// func UpdateHandlerEasyJSON(db storage.DB) func(w http.ResponseWriter, r *http.Request) {
+// 	return func(w http.ResponseWriter, r *http.Request) {
+// 		q := queriesParam(r)
+// 		worlds := make([]storage.World, q)
+// 		for i := 0; i < q; i++ {
+// 			worlds[i], _ = db.GetOneRandomWorld()
+// 		}
+// 		if err := db.UpdateWorlds(worlds, q); err != nil {
+// 			log.Println(err)
+// 			return
+// 		}
+// 		w.Header().Set("Server", "Go")
+// 		easyjson.MarshalToHTTPResponseWriter(storage.Worlds(worlds), w)
+// 	}
+// }
+
 // UpdateHandlerEasyJSON . Test 5: Database updates
 func UpdateHandlerEasyJSON(db storage.DB) func(w http.ResponseWriter, r *http.Request) {
 	return func(w http.ResponseWriter, r *http.Request) {
-		q := queriesParam(r)
+		queries := queriesParam(r)
+		worlds := storage.WorldsPool.Get().([]storage.World)[:queries]
 
-		worlds, err := db.UpdateRandomWorlds(q)
-		if err != nil {
+		for i := 0; i < queries; i++ {
+			_ = db.GetOneRandomWorld(&worlds[i])
+		}
+		if err := db.UpdateWorlds(worlds, queries); err != nil {
 			log.Println(err)
 			return
 		}
 
 		w.Header().Set("Server", "Go")
 		easyjson.MarshalToHTTPResponseWriter(storage.Worlds(worlds), w)
+		worlds = worlds[:0]
+		storage.WorldsPool.Put(worlds)
 	}
 }

+ 14 - 0
frameworks/Go/go-std/src/handlers/message.go

@@ -1,6 +1,20 @@
 package handlers
 
+import "sync"
+
 // Message struct
 type Message struct {
 	Message string `json:"message"`
 }
+
+// MessagePool *sync.Pool
+var MessagePool *sync.Pool
+
+// InitMessagePool ()
+func InitMessagePool() {
+	MessagePool = &sync.Pool{
+		New: func() interface{} {
+			return &Message{}
+		},
+	}
+}

+ 14 - 2
frameworks/Go/go-std/src/main.go

@@ -9,9 +9,19 @@ import (
 
 	"go-std/src/handlers"
 	"go-std/src/storage"
+	"go-std/src/templates"
 )
 
+func initSyncPools() {
+	handlers.InitMessagePool()
+	storage.InitWorldPool()
+	storage.InitWorldsPool()
+	templates.InitFortunesPool()
+}
+
 func main() {
+	initSyncPools()
+
 	// init flags
 	bindHost := flag.String("bind", ":8080", "set bind host")
 	prefork := flag.Bool("prefork", false, "use prefork")
@@ -46,8 +56,10 @@ func main() {
 	}
 	if db != nil {
 		defer db.Close()
-		http.HandleFunc("/fortune", handlers.FortuneHandler(db))
-		http.HandleFunc("/fortune-quick", handlers.FortuneQuickHandler(db))
+		// http.HandleFunc("/fortune", handlers.FortuneHandler(db))
+		http.HandleFunc("/fortune", handlers.FortuneHandlerPool(db))
+		// http.HandleFunc("/fortune-quick", handlers.FortuneQuickHandler(db))
+		http.HandleFunc("/fortune-quick", handlers.FortuneQuickHandlerPool(db))
 		if *easyjson {
 			http.HandleFunc("/db", handlers.DBHandlerEasyJSON(db))
 			http.HandleFunc("/queries", handlers.QueriesHandlerEasyJSON(db))

+ 15 - 11
frameworks/Go/go-std/src/storage/db.go

@@ -20,15 +20,18 @@ const (
 	fortuneQueryStrMySQL = "SELECT id, message FROM Fortune"
 )
 
-var (
+const (
 	worldsCount = 10000
 )
 
 // DB is interface for
 type DB interface {
-	GetOneRandomWorld() (World, error)
-	UpdateRandomWorlds(queries int) ([]World, error)
+	// GetOneRandomWorld() (World, error)
+	GetOneRandomWorld(*World) error
+	// UpdateWorlds([]World, int) error
+	UpdateWorlds([]World, int) error
 	GetFortunes() ([]templates.Fortune, error)
+	GetFortunesPool() ([]templates.Fortune, error)
 	Close()
 }
 
@@ -36,14 +39,8 @@ type DB interface {
 func InitDB(dbDriver, dbConnectionString string) (DB, error) {
 	var err error
 	var db DB
-	if dbDriver == "pq" {
-		db, err = NewPqDB(
-			dbConnectionString,
-			runtime.NumCPU())
-		if err != nil {
-			return nil, fmt.Errorf("Error opening postgresql database with pq driver: %s", err)
-		}
-	} else if dbDriver == "pgx" {
+
+	if dbDriver == "pgx" {
 		db, err = NewPgxDB(
 			dbConnectionString,
 			runtime.NumCPU())
@@ -64,6 +61,13 @@ func InitDB(dbDriver, dbConnectionString string) (DB, error) {
 		if err != nil {
 			return nil, fmt.Errorf("Error opening mongo database with mgo driver: %s", err)
 		}
+		// } else if dbDriver == "pq" {
+		// 	db, err = NewPqDB(
+		// 		dbConnectionString,
+		// 		runtime.NumCPU())
+		// 	if err != nil {
+		// 		return nil, fmt.Errorf("Error opening postgresql database with pq driver: %s", err)
+		// 	}
 	} else if dbDriver == "none" {
 		db = nil
 	} else {

+ 15 - 10
frameworks/Go/go-std/src/storage/mgo.go

@@ -40,23 +40,17 @@ func (mongo *Mongo) Close() {
 }
 
 // GetOneRandomWorld return one random World struct
-func (mongo Mongo) GetOneRandomWorld() (World, error) {
-	var w World
+func (mongo Mongo) GetOneRandomWorld(w *World) error {
 	var err error
 	queryID := rand.Intn(worldsCount) + 1
 	if err = mongo.worlds.Find(bson.M{"_id": queryID}).One(&w); err != nil {
 		err = fmt.Errorf("error finding world with ID %d: %s", queryID, err)
 	}
-	return w, err
+	return err
 }
 
 // UpdateRandomWorlds updates some number of worlds entries, passed as arg
-func (mongo Mongo) UpdateRandomWorlds(queries int) ([]World, error) {
-	selectedWorlds := make([]World, queries)
-	for i := 0; i < queries; i++ {
-		selectedWorlds[i], _ = mongo.GetOneRandomWorld()
-	}
-
+func (mongo Mongo) UpdateWorlds(selectedWorlds []World, queries int) error {
 	for _, selectedWorld := range selectedWorlds {
 		selectedWorld.RandomNumber = rand.Intn(worldsCount) + 1
 		if err := mongo.worlds.Update(
@@ -67,7 +61,7 @@ func (mongo Mongo) UpdateRandomWorlds(queries int) ([]World, error) {
 		}
 	}
 
-	return selectedWorlds, nil
+	return nil
 }
 
 // GetFortunes finds all fortunes from table
@@ -81,6 +75,17 @@ func (mongo Mongo) GetFortunes() ([]templates.Fortune, error) {
 	return fortunes, nil
 }
 
+// GetFortunesPool finds all fortunes from table
+func (mongo Mongo) GetFortunesPool() ([]templates.Fortune, error) {
+	fortunes := templates.FortunesPool.Get().([]templates.Fortune)
+
+	if err := mongo.fortunes.Find(nil).All(&fortunes); err != nil {
+		return nil, err
+	}
+
+	return fortunes, nil
+}
+
 // NewMongoDB creates new connection to mongodb with mgo driver
 func NewMongoDB(dbConnectionString string, maxConnectionsInPool int) (DB, error) {
 	var mongo Mongo

+ 42 - 30
frameworks/Go/go-std/src/storage/mysql.go

@@ -56,49 +56,41 @@ func (mysql *MySQL) Close() {
 }
 
 // GetOneRandomWorld return one random World struct
-func (mysql MySQL) GetOneRandomWorld() (World, error) {
-	var w World
+func (mysql MySQL) GetOneRandomWorld(w *World) error {
 	var err error
 	queryID := rand.Intn(worldsCount) + 1
 	if err = mysql.selectStmt.QueryRow(queryID).Scan(&w.ID, &w.RandomNumber); err != nil {
 		err = fmt.Errorf("error scanning world row with ID %d: %s", queryID, err)
 	}
-	return w, err
+	return err
 }
 
-// UpdateRandomWorlds updates some number of worlds entries, passed as arg
-func (mysql MySQL) UpdateRandomWorlds(queries int) ([]World, error) {
-	selectedWorlds := make([]World, queries)
-	for i := 0; i < queries; i++ {
-		selectedWorlds[i], _ = mysql.GetOneRandomWorld()
-	}
-
-	if len(selectedWorlds) > 0 {
-		// against deadlocks
-		sort.Slice(selectedWorlds, func(i, j int) bool {
-			return selectedWorlds[i].ID < selectedWorlds[j].ID
-		})
-
-		tx, err := mysql.db.Begin()
-		if err != nil {
-			return selectedWorlds, err
-		}
+// UpdateWorlds updates some number of worlds entries, passed as arg
+func (mysql MySQL) UpdateWorlds(selectedWorlds []World, queries int) error {
+	// against deadlocks
+	sort.Slice(selectedWorlds, func(i, j int) bool {
+		return selectedWorlds[i].ID < selectedWorlds[j].ID
+	})
 
-		for _, selectedWorld := range selectedWorlds {
-			selectedWorld.RandomNumber = rand.Intn(worldsCount) + 1
-			if _, err := tx.Stmt(mysql.updateStmt).Exec(selectedWorld.RandomNumber, selectedWorld.ID); err != nil {
-				log.Printf("Can't update row ID %d with number %d: %s", selectedWorld.ID, selectedWorld.RandomNumber, err)
-				tx.Rollback()
-			}
-		}
+	tx, err := mysql.db.Begin()
+	if err != nil {
+		return err
+	}
 
-		if err := tx.Commit(); err != nil {
+	for _, selectedWorld := range selectedWorlds {
+		selectedWorld.RandomNumber = rand.Intn(worldsCount) + 1
+		if _, err := tx.Stmt(mysql.updateStmt).Exec(selectedWorld.RandomNumber, selectedWorld.ID); err != nil {
+			log.Printf("Can't update row ID %d with number %d: %s", selectedWorld.ID, selectedWorld.RandomNumber, err)
 			tx.Rollback()
-			return selectedWorlds, err
 		}
 	}
 
-	return selectedWorlds, nil
+	if err := tx.Commit(); err != nil {
+		tx.Rollback()
+		return err
+	}
+
+	return nil
 }
 
 // GetFortunes selects all fortunes from table
@@ -121,6 +113,26 @@ func (mysql MySQL) GetFortunes() ([]templates.Fortune, error) {
 	return fortunes, nil
 }
 
+// GetFortunesPool selects all fortunes from table
+func (mysql MySQL) GetFortunesPool() ([]templates.Fortune, error) {
+	rows, err := mysql.fortuneStmt.Query()
+	defer rows.Close()
+	if err != nil {
+		return nil, fmt.Errorf("can't query fortunes: %s", err)
+	}
+
+	fortunes := templates.FortunesPool.Get().([]templates.Fortune)
+	var fortune templates.Fortune
+	for rows.Next() {
+		if err = rows.Scan(&fortune.ID, &fortune.Message); err != nil {
+			log.Printf("Can't scan fortune: %s\n", err)
+		}
+		fortunes = append(fortunes, fortune)
+	}
+
+	return fortunes, nil
+}
+
 func (mysql MySQL) mustPrepare(query string) (*sql.Stmt, error) {
 	stmt, err := mysql.db.Prepare(query)
 	if err != nil {

+ 49 - 29
frameworks/Go/go-std/src/storage/pgx.go

@@ -65,49 +65,49 @@ func (psql *PGX) Close() {
 }
 
 // GetOneRandomWorld return one random World struct
-func (psql PGX) GetOneRandomWorld() (World, error) {
-	var w World
+func (psql PGX) GetOneRandomWorld(w *World) error {
 	var err error
 	queryID := rand.Intn(worldsCount) + 1
 	if err = psql.db.QueryRow("selectStmt", queryID).Scan(&w.ID, &w.RandomNumber); err != nil {
 		err = fmt.Errorf("error scanning world row with ID %d: %s", queryID, err)
 	}
-	return w, err
+	return err
 }
 
-// UpdateRandomWorlds updates some number of worlds entries, passed as arg
-func (psql PGX) UpdateRandomWorlds(queries int) ([]World, error) {
-	selectedWorlds := make([]World, queries)
-	for i := 0; i < queries; i++ {
-		selectedWorlds[i], _ = psql.GetOneRandomWorld()
-	}
+// UpdateWorlds updates some number of worlds entries, passed as arg
+func (psql PGX) UpdateWorlds(selectedWorlds []World, queries int) error {
+	// against deadlocks
+	sort.Slice(selectedWorlds, func(i, j int) bool {
+		return selectedWorlds[i].ID < selectedWorlds[j].ID
+	})
 
-	if len(selectedWorlds) > 0 {
-		// against deadlocks
-		sort.Slice(selectedWorlds, func(i, j int) bool {
-			return selectedWorlds[i].ID < selectedWorlds[j].ID
-		})
+	tx, err := psql.db.Begin()
+	if err != nil {
+		return err
+	}
 
-		tx, err := psql.db.Begin()
-		if err != nil {
-			return selectedWorlds, err
+	for _, selectedWorld := range selectedWorlds {
+		selectedWorld.RandomNumber = rand.Intn(worldsCount) + 1
+		if _, err := tx.Exec("updateStmt", selectedWorld.RandomNumber, selectedWorld.ID); err != nil {
+			log.Printf("Can't update row ID %d with number %d: %s", selectedWorld.ID, selectedWorld.RandomNumber, err)
+			tx.Rollback()
 		}
+	}
 
-		for _, selectedWorld := range selectedWorlds {
-			selectedWorld.RandomNumber = rand.Intn(worldsCount) + 1
-			if _, err := tx.Exec("updateStmt", selectedWorld.RandomNumber, selectedWorld.ID); err != nil {
-				log.Printf("Can't update row ID %d with number %d: %s", selectedWorld.ID, selectedWorld.RandomNumber, err)
-				tx.Rollback()
-			}
-		}
+	// for i := 0; i < queries; i++ {
+	// 	selectedWorlds[i].RandomNumber = rand.Intn(worldsCount) + 1
+	// 	if _, err := tx.Exec("updateStmt", selectedWorlds[i].RandomNumber, selectedWorlds[i].ID); err != nil {
+	// 		log.Printf("Can't update row ID %d with number %d: %s", selectedWorlds[i].ID, selectedWorlds[i].RandomNumber, err)
+	// 		tx.Rollback()
+	// 	}
+	// }
 
-		if err := tx.Commit(); err != nil {
-			tx.Rollback()
-			return selectedWorlds, err
-		}
+	if err := tx.Commit(); err != nil {
+		tx.Rollback()
+		return err
 	}
 
-	return selectedWorlds, nil
+	return nil
 }
 
 // GetFortunes selects all fortunes from table
@@ -130,6 +130,26 @@ func (psql PGX) GetFortunes() ([]templates.Fortune, error) {
 	return fortunes, nil
 }
 
+// GetFortunesPool selects all fortunes from table
+func (psql PGX) GetFortunesPool() ([]templates.Fortune, error) {
+	rows, err := psql.db.Query("fortuneStmt")
+	defer rows.Close()
+	if err != nil {
+		return nil, fmt.Errorf("can't query fortunes: %s", err)
+	}
+
+	fortunes := templates.FortunesPool.Get().([]templates.Fortune)
+	var fortune templates.Fortune
+	for rows.Next() {
+		if err = rows.Scan(&fortune.ID, &fortune.Message); err != nil {
+			log.Printf("Can't scan fortune: %s\n", err)
+		}
+		fortunes = append(fortunes, fortune)
+	}
+
+	return fortunes, nil
+}
+
 func mustPrepare(db *pgx.Conn, name, query string) (*pgx.PreparedStatement, error) {
 	stmt, err := db.Prepare(name, query)
 	if err != nil {

+ 138 - 138
frameworks/Go/go-std/src/storage/pq.go

@@ -1,140 +1,140 @@
 package storage
 
-import (
-	"database/sql"
-	"fmt"
-	"log"
-	"math/rand"
-	"sort"
-
-	"go-std/src/templates"
-
-	_ "github.com/lib/pq" // postgresql import
-)
-
-// PQ struct
-type PQ struct {
-	db *sql.DB
-	// prepare statements
-	selectStmt  *sql.Stmt
-	updateStmt  *sql.Stmt
-	fortuneStmt *sql.Stmt
-}
-
-// Connect create connection and ping db
-func (psql *PQ) Connect(dbConnectionString string, maxConnectionsInPool int) error {
-	var err error
-	psql.db, err = sql.Open("postgres", dbConnectionString)
-	if err != nil {
-		return err
-	}
-
-	err = psql.db.Ping()
-	if err != nil {
-		return err
-	}
-
-	psql.db.SetMaxOpenConns(maxConnectionsInPool)
-	psql.db.SetMaxIdleConns(maxConnectionsInPool)
-
-	if psql.selectStmt, err = psql.mustPrepare(selectQueryStrPostgre); err != nil {
-		return err
-	}
-	if psql.fortuneStmt, err = psql.mustPrepare(fortuneQueryStrPostgre); err != nil {
-		return err
-	}
-	if psql.updateStmt, err = psql.mustPrepare(updateQueryStrPostgre); err != nil {
-		return err
-	}
-
-	return nil
-}
-
-// Close connect to db
-func (psql *PQ) Close() {
-	psql.db.Close()
-}
-
-// GetOneRandomWorld return one random World struct
-func (psql PQ) GetOneRandomWorld() (World, error) {
-	var w World
-	var err error
-	queryID := rand.Intn(worldsCount) + 1
-	if err = psql.selectStmt.QueryRow(queryID).Scan(&w.ID, &w.RandomNumber); err != nil {
-		err = fmt.Errorf("error scanning world row with ID %d: %s", queryID, err)
-	}
-	return w, err
-}
-
-// UpdateRandomWorlds updates some number of worlds entries, passed as arg
-func (psql PQ) UpdateRandomWorlds(queries int) ([]World, error) {
-	selectedWorlds := make([]World, queries)
-	for i := 0; i < queries; i++ {
-		selectedWorlds[i], _ = psql.GetOneRandomWorld()
-	}
-
-	if len(selectedWorlds) > 0 {
-		// against deadlocks
-		sort.Slice(selectedWorlds, func(i, j int) bool {
-			return selectedWorlds[i].ID < selectedWorlds[j].ID
-		})
-
-		tx, err := psql.db.Begin()
-		if err != nil {
-			return selectedWorlds, err
-		}
-
-		for _, selectedWorld := range selectedWorlds {
-			selectedWorld.RandomNumber = rand.Intn(worldsCount) + 1
-			if _, err := tx.Stmt(psql.updateStmt).Exec(selectedWorld.RandomNumber, selectedWorld.ID); err != nil {
-				log.Printf("Can't update row ID %d with number %d: %s", selectedWorld.ID, selectedWorld.RandomNumber, err)
-				tx.Rollback()
-			}
-		}
-
-		if err := tx.Commit(); err != nil {
-			tx.Rollback()
-			return selectedWorlds, err
-		}
-	}
-
-	return selectedWorlds, nil
-}
-
-// GetFortunes selects all fortunes from table
-func (psql PQ) GetFortunes() ([]templates.Fortune, error) {
-	rows, err := psql.fortuneStmt.Query()
-	defer rows.Close()
-	if err != nil {
-		return nil, fmt.Errorf("can't query fortunes: %s", err)
-	}
-
-	fortunes := make([]templates.Fortune, 0, 16)
-	var fortune templates.Fortune
-	for rows.Next() {
-		if err = rows.Scan(&fortune.ID, &fortune.Message); err != nil {
-			log.Printf("Can't scan fortune: %s\n", err)
-		}
-		fortunes = append(fortunes, fortune)
-	}
-
-	return fortunes, nil
-}
-
-func (psql PQ) mustPrepare(query string) (*sql.Stmt, error) {
-	stmt, err := psql.db.Prepare(query)
-	if err != nil {
-		log.Printf("Error when preparing statement %q: %s\n", query, err)
-		return nil, err
-	}
-	return stmt, nil
-}
-
-// NewPqDB creates new connection to postgres db with pq driver
-func NewPqDB(dbConnectionString string, maxConnectionsInPool int) (DB, error) {
-	var psql PQ
-	if err := psql.Connect(dbConnectionString, maxConnectionsInPool); err != nil {
-		return nil, err
-	}
-	return &psql, nil
-}
+// import (
+// 	"database/sql"
+// 	"fmt"
+// 	"log"
+// 	"math/rand"
+// 	"sort"
+
+// 	"go-std/src/templates"
+
+// 	_ "github.com/lib/pq" // postgresql import
+// )
+
+// // PQ struct
+// type PQ struct {
+// 	db *sql.DB
+// 	// prepare statements
+// 	selectStmt  *sql.Stmt
+// 	updateStmt  *sql.Stmt
+// 	fortuneStmt *sql.Stmt
+// }
+
+// // Connect create connection and ping db
+// func (psql *PQ) Connect(dbConnectionString string, maxConnectionsInPool int) error {
+// 	var err error
+// 	psql.db, err = sql.Open("postgres", dbConnectionString)
+// 	if err != nil {
+// 		return err
+// 	}
+
+// 	err = psql.db.Ping()
+// 	if err != nil {
+// 		return err
+// 	}
+
+// 	psql.db.SetMaxOpenConns(maxConnectionsInPool)
+// 	psql.db.SetMaxIdleConns(maxConnectionsInPool)
+
+// 	if psql.selectStmt, err = psql.mustPrepare(selectQueryStrPostgre); err != nil {
+// 		return err
+// 	}
+// 	if psql.fortuneStmt, err = psql.mustPrepare(fortuneQueryStrPostgre); err != nil {
+// 		return err
+// 	}
+// 	if psql.updateStmt, err = psql.mustPrepare(updateQueryStrPostgre); err != nil {
+// 		return err
+// 	}
+
+// 	return nil
+// }
+
+// // Close connect to db
+// func (psql *PQ) Close() {
+// 	psql.db.Close()
+// }
+
+// // GetOneRandomWorld return one random World struct
+// func (psql PQ) GetOneRandomWorld() (World, error) {
+// 	var w World
+// 	var err error
+// 	queryID := rand.Intn(worldsCount) + 1
+// 	if err = psql.selectStmt.QueryRow(queryID).Scan(&w.ID, &w.RandomNumber); err != nil {
+// 		err = fmt.Errorf("error scanning world row with ID %d: %s", queryID, err)
+// 	}
+// 	return w, err
+// }
+
+// // UpdateRandomWorlds updates some number of worlds entries, passed as arg
+// func (psql PQ) UpdateRandomWorlds(queries int) ([]World, error) {
+// 	selectedWorlds := make([]World, queries)
+// 	for i := 0; i < queries; i++ {
+// 		selectedWorlds[i], _ = psql.GetOneRandomWorld()
+// 	}
+
+// 	if len(selectedWorlds) > 0 {
+// 		// against deadlocks
+// 		sort.Slice(selectedWorlds, func(i, j int) bool {
+// 			return selectedWorlds[i].ID < selectedWorlds[j].ID
+// 		})
+
+// 		tx, err := psql.db.Begin()
+// 		if err != nil {
+// 			return selectedWorlds, err
+// 		}
+
+// 		for _, selectedWorld := range selectedWorlds {
+// 			selectedWorld.RandomNumber = rand.Intn(worldsCount) + 1
+// 			if _, err := tx.Stmt(psql.updateStmt).Exec(selectedWorld.RandomNumber, selectedWorld.ID); err != nil {
+// 				log.Printf("Can't update row ID %d with number %d: %s", selectedWorld.ID, selectedWorld.RandomNumber, err)
+// 				tx.Rollback()
+// 			}
+// 		}
+
+// 		if err := tx.Commit(); err != nil {
+// 			tx.Rollback()
+// 			return selectedWorlds, err
+// 		}
+// 	}
+
+// 	return selectedWorlds, nil
+// }
+
+// // GetFortunes selects all fortunes from table
+// func (psql PQ) GetFortunes() ([]templates.Fortune, error) {
+// 	rows, err := psql.fortuneStmt.Query()
+// 	defer rows.Close()
+// 	if err != nil {
+// 		return nil, fmt.Errorf("can't query fortunes: %s", err)
+// 	}
+
+// 	fortunes := make([]templates.Fortune, 0, 16)
+// 	var fortune templates.Fortune
+// 	for rows.Next() {
+// 		if err = rows.Scan(&fortune.ID, &fortune.Message); err != nil {
+// 			log.Printf("Can't scan fortune: %s\n", err)
+// 		}
+// 		fortunes = append(fortunes, fortune)
+// 	}
+
+// 	return fortunes, nil
+// }
+
+// func (psql PQ) mustPrepare(query string) (*sql.Stmt, error) {
+// 	stmt, err := psql.db.Prepare(query)
+// 	if err != nil {
+// 		log.Printf("Error when preparing statement %q: %s\n", query, err)
+// 		return nil, err
+// 	}
+// 	return stmt, nil
+// }
+
+// // NewPqDB creates new connection to postgres db with pq driver
+// func NewPqDB(dbConnectionString string, maxConnectionsInPool int) (DB, error) {
+// 	var psql PQ
+// 	if err := psql.Connect(dbConnectionString, maxConnectionsInPool); err != nil {
+// 		return nil, err
+// 	}
+// 	return &psql, nil
+// }

+ 26 - 0
frameworks/Go/go-std/src/storage/world.go

@@ -1,5 +1,7 @@
 package storage
 
+import "sync"
+
 //easyjson:json
 type World struct {
 	ID           int `json:"id"`
@@ -8,3 +10,27 @@ type World struct {
 
 //easyjson:json
 type Worlds []World
+
+// WorldPool *sync.Pool
+var WorldPool *sync.Pool
+
+// InitWorldPool ()
+func InitWorldPool() {
+	WorldPool = &sync.Pool{
+		New: func() interface{} {
+			return &World{}
+		},
+	}
+}
+
+// WorldsPool *sync.Pool
+var WorldsPool *sync.Pool
+
+// InitWorldsPool ()
+func InitWorldsPool() {
+	WorldsPool = &sync.Pool{
+		New: func() interface{} {
+			return make([]World, 0, 512)
+		},
+	}
+}

+ 16 - 1
frameworks/Go/go-std/src/templates/fortune.go

@@ -1,6 +1,9 @@
 package templates
 
-import "html/template"
+import (
+	"html/template"
+	"sync"
+)
 
 //go:generate qtc
 
@@ -37,3 +40,15 @@ type Fortune struct {
 	ID      int    `json:"id,omitempty"`
 	Message string `json:"message,omitempty"`
 }
+
+// FortunesPool *sync.Pool
+var FortunesPool *sync.Pool
+
+// InitFortunesPool ()
+func InitFortunesPool() {
+	FortunesPool = &sync.Pool{
+		New: func() interface{} {
+			return make([]Fortune, 0, 16)
+		},
+	}
+}

+ 1 - 1
frameworks/Go/iris/iris-pgx-prefork.dockerfile

@@ -1,4 +1,4 @@
-FROM golang:1.11.5
+FROM golang:1.12
 
 ENV GO111MODULE on
 WORKDIR /iris

+ 1 - 1
frameworks/Go/iris/iris-pgx-quicktemplate-prefork.dockerfile

@@ -1,4 +1,4 @@
-FROM golang:1.11.5
+FROM golang:1.12
 
 ENV GO111MODULE on
 WORKDIR /iris

+ 1 - 1
frameworks/Go/iris/iris-pgx-quicktemplate.dockerfile

@@ -1,4 +1,4 @@
-FROM golang:1.11.5
+FROM golang:1.12
 
 ENV GO111MODULE on
 WORKDIR /iris

+ 1 - 1
frameworks/Go/iris/iris-pgx.dockerfile

@@ -1,4 +1,4 @@
-FROM golang:1.11.5
+FROM golang:1.12
 
 ENV GO111MODULE on
 WORKDIR /iris

+ 1 - 1
frameworks/Go/iris/iris-prefork.dockerfile

@@ -1,4 +1,4 @@
-FROM golang:1.11.5
+FROM golang:1.12
 
 ENV GO111MODULE on
 WORKDIR /iris

+ 1 - 1
frameworks/Go/iris/iris.dockerfile

@@ -1,4 +1,4 @@
-FROM golang:1.11.5
+FROM golang:1.12
 
 ENV GO111MODULE on
 WORKDIR /iris