# golang Gorm orm & org sqllite
# install sqlite3
```
go get -u github.com/mattn/go-sqlite3
http://tw.gitbook.net/sqlite/sqlite_create_database.html
```
# create sqlite3 database
```sql=
CREATE TABLE `userinfo` (
`uid` INTEGER PRIMARY KEY AUTOINCREMENT,
`username` VARCHAR(64) NULL,
`department` VARCHAR(64) NULL,
`created` DATE NULL
);
CREATE TABLE `userdetail` (
`uid` INT(10) NULL,
`intro` TEXT NULL,
`profile` TEXT NULL,
PRIMARY KEY (`uid`)
);
```
![](https://i.imgur.com/XqCUkvO.png)
```go=
func main() {
http.HandleFunc("/endpoint-2", handler2)
}
func handler2(w http.ResponseWriter, r *http.Request) {
b, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fmt.Println("all nowgoroutine :", runtime.NumGoroutine())
go func() {
// Block until there are fewer than cap(smallPool) hard-work
// goroutines running.
smallPool <- struct{}{}
defer func() { <-smallPool }() // Let everyone that we are done
fmt.Println("working!")
time.Sleep(5 * time.Second)
fmt.Println("work done")
processImage(b)
}()
// w.WriteHeader(http.StatusAccepted)
a += 1
// time.Sleep(2 * time.Second)
if runtime.NumGoroutine() < 20 {
db, err := sql.Open("sqlite3", "./foo.db")
checkErr(err)
rows, err := db.Query("SELECT * FROM userinfo")
checkErr(err)
var output string = ""
for rows.Next() {
var uid int
var username string
var department string
var created time.Time
err = rows.Scan(&uid, &username, &department, &created)
checkErr(err)
output += strconv.Itoa(uid) + "|" + username + "|" + department + "|" + created.Format("2006-01-02 15:04:05") + "\n"
}
w.Write([]byte(output))
w.WriteHeader(http.StatusAccepted)
db.Close()
} else {
// w.Write([]byte("pleass wait" + strconv.Itoa(a)))
w.WriteHeader(http.StatusNotFound)
return
// http.ErrUseLastResponse
}
}
```
# orm
https://blog.csdn.net/cnwyt/article/details/118904882
```
go get -u gorm.io/gorm
go get -u gorm.io/driver/sqlite
```
```go=
func main (){
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// Migrate the schema
db.AutoMigrate(&Product{})
// 插入內容
db.Create(&Product{Title: "新款手機", Code: "D42", Price: 1000})
db.Create(&Product{Title: "新款電腦", Code: "D43", Price: 3500})
// 讀取內容
var product Product
db.First(&product, 1) // find product with integer primary key
db.First(&product, "code = ?", "D42") // find product with code D42
fmt.Println("%v", product)
// 更新操作: 更新單個字段
db.Model(&product).Update("Price", 2000)
// 更新操作: 更新多個字段
db.Model(&product).Updates(Product{Price: 2000, Code: "F42"}) // non-zero fields
db.Model(&product).Updates(map[string]interface{}{"Price": 2000, "Code": "F42"})
// 刪除操作:
db.Delete(&product, 1)
}
```
# sql pool & http pool
https://codertw.com/%E4%BC%BA%E6%9C%8D%E5%99%A8/154458/
https://gorm.io/docs/connecting_to_the_database.html
實際上在經過查詢可以發現,預設的http 或者 sql 其實底層都是goroutines,則我們也不用像以前的程式去寫 pool 之類的我們只要全局的去宣告就好
global variable
```go=
func connDB(lifeTime int, maxCon int, idle int) *gorm.DB {
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
sqlDB, err := db.DB()
if err != nil {
panic(err)
}
sqlDB.SetConnMaxLifetime(time.Duration(lifeTime) * time.Second) // 每條連線的存活時間
sqlDB.SetMaxOpenConns(maxCon) // 最大連線數
sqlDB.SetMaxIdleConns(idle) // 最大閒置連線數
return db
}
func init() {
DBConn = connDB(1, 200, 10)
// Migrate the schema
DBConn.AutoMigrate(&Product{})
// 插入內容
DBConn.Create(&Product{Title: "新款手機", Code: "D42", Price: 1000})
DBConn.Create(&Product{Title: "新款電腦", Code: "D43", Price: 3500})
// 讀取內容
var product Product
DBConn.First(&product, 1) // find product with integer primary key
DBConn.First(&product, "code = ?", "D42") // find product with code D42
fmt.Println("%v", product)
// 更新操作: 更新單個字段
DBConn.Model(&product).Update("Price", 2000)
// 更新操作: 更新多個字段
DBConn.Model(&product).Updates(Product{Price: 2000, Code: "F42"}) // non-zero fields
DBConn.Model(&product).Updates(map[string]interface{}{"Price": 2000, "Code": "F42"})
// 刪除操作:
DBConn.Delete(&product, 1)
}
func main (){
http.HandleFunc("/endpoint-2", handler2)
}
func handler2(w http.ResponseWriter, r *http.Request) {
b, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fmt.Println("all nowgoroutine :", runtime.NumGoroutine())
go func() {
// Block until there are fewer than cap(smallPool) hard-work
// goroutines running.
smallPool <- struct{}{}
defer func() { <-smallPool }() // Let everyone that we are done
fmt.Println("working!")
time.Sleep(5 * time.Second)
fmt.Println("work done")
processImage(b)
}()
// w.WriteHeader(http.StatusAccepted)
a += 1
// time.Sleep(2 * time.Second)
if runtime.NumGoroutine() < 20 {
// 讀取內容
var product Product
DBConn.First(&product, 1) // find product with integer primary key
DBConn.First(&product, "code = ?", "D42") // find product with code D42
fmt.Println("%v", product)
// 更新操作: 更新單個字段
DBConn.Model(&product).Update("Price", 2000)
b, err := json.Marshal(product)
if err != nil {
fmt.Println(err)
return
}
w.Write([]byte(string(b)))
w.WriteHeader(http.StatusAccepted)
// db.Close()
} else {
// w.Write([]byte("pleass wait" + strconv.Itoa(a)))
w.WriteHeader(http.StatusNotFound)
return
// http.ErrUseLastResponse
}
}
```
這樣我們的grom 就可以有pool 了
https://ithelp.ithome.com.tw/articles/10238565
![](https://i.imgur.com/6uNFCSi.png)
# http request 阻塞(?
預設 golang 的 http 都是非阻塞,原因就是chrome or edge 會將當前頁面去做緩存之類的東西,所以假設同一個畫面不同分頁可能會出現順序返回,但是實際上是瀏覽器的關係,每一個request 都是 一個Goroutine則
下面畫面是同時訪問http://localhost:8080/endpoint-2 但是在同一個瀏覽器的畫面,可以看到右邊會有出現阻塞現象
![](https://i.imgur.com/JeugCZb.png)
下面是一個edge 和 chrome
同時訪問可以看到時間戳相差不遠
![](https://i.imgur.com/Sf1aXOq.png)