2018/06/27 21:21:12 http: panic serving 10.105.107.106:41488: runtime error: invalid memory address or nil pointer dereference
goroutine 1238 [running]:
net/http.(*conn).serve.func1(0xc420195a40)
/usr/local/go/src/net/http/server.go:1726 +0xd0
panic(0x701840, 0x91fd70)
/usr/local/go/src/runtime/panic.go:502 +0x229
database/sql.(*Stmt).ExecContext(0x0, 0x7a82a0, 0xc4200160d0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
/usr/local/go/src/database/sql/sql.go:2224 +0x4a
database/sql.(*Stmt).Exec(0x0, 0x0, 0x0, 0x0, 0x7efe6b4862a8, 0xc4201ce600, 0x0, 0xc42017e555)
/usr/local/go/src/database/sql/sql.go:2253 +0x65
main.mpp(0x7a7fe0, 0xc4203421c0, 0xc420332500)
/root/golang_mysql_proxy_pool/pool.go:151 +0x12e1
net/http.HandlerFunc.ServeHTTP(0x77e138, 0x7a7fe0, 0xc4203421c0, 0xc420332500)
/usr/local/go/src/net/http/server.go:1947 +0x44
net/http.(*ServeMux).ServeHTTP(0x92c0a0, 0x7a7fe0, 0xc4203421c0, 0xc420332500)
/usr/local/go/src/net/http/server.go:2337 +0x130
net/http.serverHandler.ServeHTTP(0xc420097110, 0x7a7fe0, 0xc4203421c0, 0xc420332500)
/usr/local/go/src/net/http/server.go:2694 +0xbc
net/http.(*conn).serve(0xc420195a40, 0x7a8260, 0xc4201d0800)
/usr/local/go/src/net/http/server.go:1830 +0x651
created by net/http.(*Server).Serve
/usr/local/go/src/net/http/server.go:2795 +0x27b
database/sql.(Stmt).Exec(0x0, 0x0, 0x0, 0x0, 0x7efe6b4862a8, 0xc4201ce600, 0x0, 0xc42017e555)
/usr/local/go/src/database/sql/sql.go:2253 +0x65
main.mpp(0x7a7fe0, 0xc4203421c0, 0xc420332500)
/root/golang_mysql_proxy_pool/pool.go:151 +0x12e1
stmt, _ := dbx.Prepare(query)
res, _ := stmt.Exec()
`dbx.Prepare(query)`返回的error要检查下,不要忽略函数返回的error,哪怕你认为这个error不可能发生
#4
更多评论
空指针 但不知道在哪里 贴代码
![WX20180627-214530@2x.png](https://static.studygolang.com/180627/118d9ef83b0a4575294c22570a13939a.png)
#1
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
_ "github.com/lib/pq"
_ "github.com/ziutek/mymysql/godrv"
"log"
"net/http"
// "strings"
"encoding/json"
// "os"
"regexp"
"runtime"
"strconv"
"time"
)
// /**
var config = readConfig()
// fmt.Println(config)
// var max_pool = strconv.ParseInt(string(config["max_pool_size"]), 10, 0)
// **/
var MAX_POOL_SIZE = 10
var MySQLPool chan *sql.DB
func getPool() *sql.DB {
config := readConfig()
parallel_num, _ := strconv.ParseInt(config["parallel_num"], 10, 0)
runtime.GOMAXPROCS(int(parallel_num))
dbAdapter := config["db_adapter"]
dbhost := config["dbhost"]
dbport := config["dbport"]
dbuser := config["dbuser"]
dbpwd := config["dbpwd"]
dbname := config["dbname"]
// fmt.Println(config)
// fmt.Println(config["bind"])
if MySQLPool == nil {
MySQLPool = make(chan *sql.DB, MAX_POOL_SIZE)
}
if len(MySQLPool) == 0 { //if no DB conn, we make the pool
max_pool, _ := strconv.ParseInt(config["max_pool_size"], 10, 0)
// fmt.Println(max_pool)
go func() {
for i := 0; i < int(max_pool); i++ {
fmt.Println("crean DB conn....")
// mysqlc, err := sql.Open("mymysql", "tcp:127.0.0.1:3306*test/root/")
if dbAdapter == "mysql" {
//mysql conn
mysqlc, err := sql.Open("mymysql", "tcp:"+dbhost+":"+dbport+"*"+dbname+"/"+dbuser+"/"+dbpwd)
if err != nil {
panic(err)
}
putPool(mysqlc)
} else if dbAdapter == "pgsql" {
//pgsql conn
// mysqlc, err := sql.Open("postgres", "user=postgres_user password=password host=172.16.2.29 dbname=my_postgres_db sslmode=disable")
postgrec, err := sql.Open("postgres", "user="+dbuser+" password="+dbpwd+" host="+dbhost+" port="+dbport+" dbname="+dbname+" sslmode=disable")
if err != nil {
panic(err)
}
putPool(postgrec)
}
}
}()
}
return <-MySQLPool //parallel return DB conn use pool
}
func putPool(conn *sql.DB) {
// fmt.Println("crean DB conn....")
if MySQLPool == nil {
MySQLPool = make(chan *sql.DB, MAX_POOL_SIZE)
}
if len(MySQLPool) == MAX_POOL_SIZE {
conn.Close()
return
}
MySQLPool <- conn
}
func mpp(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
/**
* the json return back
* code 0 is for success
* 1 is for wrong query
* 2 is for wrong get data
* status success or fail
* rows query data
**/
var back = make(map[string]interface{}) //return json
back["code"] = 0
back["status"] = "success"
back["rows"] = ""
var errCode = 0
uukey := r.FormValue("uukey")
if uukey != config["uukey"] {
back["code"] = 3
back["status"] = "fail"
// log.Fatal("uukey not the same")
errCode = 1
}
cache := r.FormValue("cache") //cache enable
ccKey := r.FormValue("cache_key") //cache key
ccTime := r.FormValue("cctime") //cache time
if errCode == 0 { //check secure uukey
query := r.FormValue("query")
fmt.Println("query is: ", query)
// os.Exit(3)
//get cache info
if query == "cc_info" { //get all cache info
// ccInfo()
cc_info := ccInfo()
fmt.Fprintf(w, cc_info)
return
} else if config["cache"] == "1" && query == "cc_get" { //get cache by key
// ccGet(ccKey)
fmt.Fprintf(w, ccGet(ccKey))
return
}
//get DB data
dbx := getPool() //get the DB conn from pool when we want to use
//regular check sql insert/update/delete
querySelect := 1
matchedI, _ := regexp.MatchString("insert.*", query)
matchedD, _ := regexp.MatchString("delete.*", query)
matchedU, _ := regexp.MatchString("update.*", query)
// fmt.Println("regular query: ", matched)
//if not select query
if matchedI || matchedD || matchedU {
// fmt.Println("not select query")
stmt, _ := dbx.Prepare(query)
res, _ := stmt.Exec()
// fmt.Println("res: ", res)
// return res.RowsAffected()
affect, _ := res.RowsAffected()
// fmt.Println("affect: ", affect)
back["rows"] = int(affect)
// back["rows"] = 1
querySelect = 0
// return
} else {
// var rows interface{}
// rows, errQuery := dbx.Query(query)
rows, errQuery := dbx.Query(query)
// rows, affRows, errQuery := dbx.Query(query)
// fmt.Println("rows: ", rows)
// fmt.Println("affRows: ", affRows)
// fmt.Println("affRows: ", rows.RowsAffected())
if errQuery != nil {
back["code"] = 1
back["status"] = "fail"
// log.Fatal(err)
fmt.Println(errQuery)
errCode = 1
}
if errQuery == nil {
// var email string
colNames, err := rows.Columns()
checkErr(err)
readCols := make([]interface{}, len(colNames))
writeCols := make([][]byte, len(colNames))
// writeCols := make([]byte, len(colNames))
// writeCols := make([]interface{}, len(colNames))
for i, _ := range writeCols {
readCols[i] = &writeCols[i]
}
result := make([]map[string]interface{}, 0)
// fmt.Println("len res:", len(result))
// fmt.Println(result)
// fmt.Println(colNames)
for rows.Next() {
if err := rows.Scan(readCols...); err != nil {
log.Fatal(err)
back["code"] = 2
back["status"] = "fail"
}
// fmt.Println(writeCols)
var tmpStr string
tmpMap := make(map[string]interface{})
for i, raw := range writeCols {
// var tmpStr string
if raw == nil {
// result[i] = "\\N"
} else {
tmpStr += string(raw)
tmpMap[colNames[i]] = string(raw)
}
}
result = append(result, tmpMap)
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
// fmt.Println(result)
// back["rows"] = resStr
back["rows"] = result
}
// defer putPool(dbx) //put the DB conn into pool after finish used
}
defer putPool(dbx) //put the DB conn into pool after finish used
//just query DB
jsback, _ := json.Marshal(back)
//if set cache
if string(config["cache"]) == "1" && cache == "1" && ccKey != "" && querySelect == 1 {
startTime := strconv.FormatInt(time.Now().Unix(), 10)
ccJsback := string(jsback) + string(config["cache_split"]) +
string(startTime) + ":" + ccTime
//store cache
// ccSet(ccKey, string(jsback))
ccSet(ccKey, string(ccJsback))
}
// jsback, _ := json.Marshal(result)
fmt.Fprintf(w, string(jsback))
// defer putPool(dbx)
}
}
}
#2