通知设置 新通知
golang执行系统shell命令,并获取返回内容
马化云 发表了文章 • 0 个评论 • 383 次浏览 • 2023-03-26 11:42
"fmt"
"os/exec"
)
func runCommand(command string) (string, error) {
cmd := exec.Command("sh", "-c", command)
output, err := cmd.CombinedOutput()
if err != nil {
return "", err
}
return string(output), nil
}
调用 runCommand 函数即可执行 shell 命令,并获取命令的输出结果。如果命令执行成功,则返回输出结果和 nil,否则返回空字符串和错误信息。需要注意的是,由于 CombinedOutput 方法会等待命令执行完毕才返回,因此在执行耗时较长的命令时可能会阻塞程序的执行。可以使用 Start 和 Wait 方法实现异步执行命令的效果。 查看全部
import (
"fmt"
"os/exec"
)
func runCommand(command string) (string, error) {
cmd := exec.Command("sh", "-c", command)
output, err := cmd.CombinedOutput()
if err != nil {
return "", err
}
return string(output), nil
}
调用 runCommand 函数即可执行 shell 命令,并获取命令的输出结果。如果命令执行成功,则返回输出结果和 nil,否则返回空字符串和错误信息。需要注意的是,由于 CombinedOutput 方法会等待命令执行完毕才返回,因此在执行耗时较长的命令时可能会阻塞程序的执行。可以使用 Start 和 Wait 方法实现异步执行命令的效果。
golang mysql count(*) 的写法
马化云 发表了文章 • 0 个评论 • 700 次浏览 • 2022-12-15 22:17
使用golang标准库 database/sql 实现:
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/lib/pq"
)
func main() {
var count int
db, err := sql.Open("postgres", "user=test password=test dbname=foo sslmode=disable")
if err != nil {
log.Fatal(err)
}
defer db.Close()
row := db.QueryRow("SELECT COUNT(*) FROM table_name")
err := row.Scan(&count)
if err != nil {
log.Fatal(err)
}
fmt.Println(count)
}
即可。
查看全部
使用golang标准库 database/sql 实现:
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/lib/pq"
)
func main() {
var count int
db, err := sql.Open("postgres", "user=test password=test dbname=foo sslmode=disable")
if err != nil {
log.Fatal(err)
}
defer db.Close()
row := db.QueryRow("SELECT COUNT(*) FROM table_name")
err := row.Scan(&count)
if err != nil {
log.Fatal(err)
}
fmt.Println(count)
}
即可。
golang mysql包 database/sql的基本操作:增删改查 (go sql操作 保存这篇文章就足够了)
马化云 发表了文章 • 0 个评论 • 719 次浏览 • 2022-12-15 12:06
下面的是一些常见的操作,如果需要写底层sql语句,使用频率极高,值得收藏。
/*
* @Author: 30daydo
* @FilePath: /go110/go-012/g012.go
* @Description: Go 数据库基本操作
*/
package main
import (
"database/sql"
"fmt"
"runtime"
_ "github.com/go-sql-driver/mysql"
)
/**
// 创建 user 表
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`name` varchar(50) COLLATE utf8mb4_general_ci NOT NULL COMMENT '姓名',
`age` int NOT NULL COMMENT '年龄',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户信息表'
**/
// 全局对象 db
var db *sql.DB
// 定义一个 user 结构体接收数据:
type user struct {
id int
age int
name string
}
// 始化数据库的函数
func initDB() (err error) {
// 构建连接的 dsn 格式是:"用户名:密码@tcp(IP:端口)/数据库?charset=utf8"
dsn := "user:password@tcp(127.0.0.1:3306)/sql_test?charset=utf8mb4&parseTime=True"
// 给全局变量赋值, 注意这里不要使用 :=
db, err = sql.Open("mysql", dsn)
if err != nil {
fmt.Println("初始化数据库失败")
return err
}
// 校验dsn是否正确
fmt.Println("尝试与数据库建立连接...")
err = db.Ping()
if err != nil {
fmt.Println("连接失败")
return err
}
fmt.Println("连接成功")
db.SetMaxOpenConns(2000) // 设置最大打开连接数
db.SetMaxIdleConns(10) // 设置最大空闲连接数
return nil
}
// 插入数据
func insertRow(name string, age int) int64 {
sqlStr := "INSERT INTO user(name, age) VALUES (?,?)"
ret, err := db.Exec(sqlStr, name, age)
if err != nil {
fmt.Printf("插入失败, err: %v\n", err)
return 0
}
// 新插入数据的 id
insertId, err := ret.LastInsertId()
if err != nil {
fmt.Printf("获取新插入数据的 ID 失败, err:%v\n", err)
return 0
}
fmt.Printf("插入成功, ID 为 %d.\n", insertId)
return insertId
}
// 查询单条数据记录
func queryRow(rowId int64) {
sqlStr := "SELECT id, name, age FROM user WHERE id = ?"
var u user
// 确保 QueryRow 之后调用 Scan 方法,释放持有的数据库链接
err := db.QueryRow(sqlStr, rowId).Scan(&u.id, &u.name, &u.age)
if err != nil {
fmt.Printf("未找到记录, 查询失败, err: %v\n", err)
return
}
fmt.Printf("查询数据成功, id: %d name: %s age: %d \n", u.id, u.name, u.age)
}
// 更新数据
func updateRow(rowId int64, newAge int) {
sqlStr := "UPDATE user SET age=? WHERE id = ?"
ret, err := db.Exec(sqlStr, newAge, rowId)
if err != nil {
fmt.Printf("更新失败 , err:%v\n", err)
return
}
// 操作影响的行数
n, err := ret.RowsAffected()
if err != nil {
fmt.Printf("获取影响函数失败, err: %v\n", err)
return
}
fmt.Printf("更新成功, 影响行数为: %d\n", n)
}
// 删除数据
func deleteRow(rowId int64) {
sqlStr := "DELETE FROM user WHERE id = ?"
ret, err := db.Exec(sqlStr, rowId)
if err != nil {
fmt.Printf("删除失败, err: %v\n", err)
return
}
n, err := ret.RowsAffected() // 操作影响的行数
if err != nil {
fmt.Printf("获取影响函数失败, err: %v\n", err)
return
}
fmt.Printf("删除成功, 影响行数为: %d\n", n)
}
// 查询多行
func queryMultiRow() {
sqlStr := "SELECT id, name, age FROM user WHERE id > ?"
rows, err := db.Query(sqlStr, 0)
if err != nil {
fmt.Printf("查询失败, err:%v\n", err)
return
}
// 重要:关闭 rows, 释放持有的数据库链接
defer rows.Close()
// 循环读取结果集中的数据
for rows.Next() {
var u user
err := rows.Scan(&u.id, &u.name, &u.age)
if err != nil {
fmt.Printf("查询多行数据失败, err:%v\n", err)
return
}
fmt.Printf("当前数据 id: %d name: %s age: %d\n", u.id, u.name, u.age)
}
}
func main() {
// 使用内置函数打印
println("Hello", "菜鸟实战")
// 初始化数据库
initDB()
// 插入数据
var id1 = insertRow("唐遇春", 17)
var id2 = insertRow("冯显", 38)
var id3 = insertRow("花千里", 20)
// 查询多行数据
queryMultiRow()
// 更新数据
updateRow(id2, 35)
// 查询单行数据
queryRow(id2)
// 删除数据
deleteRow(id1)
// 查询多行数据
queryMultiRow()
queryRow(id3)
// 当前版本
fmt.Printf("版本: %s \n", runtime.Version())
}
当然,上面的语句也可以不用Prepare的写法,直接插入进去:
func insertDirect() {
db, err := sql.Open("mysql",
"username:password@tcp(127.0.0.1:3306)/test_db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
sql := "INSERT INTO user(id, name, pwd) VALUES(?, ?, ?)"
res, err := db.Exec(sql, 13, "Jobs", "444555")
checkErr(err)
fmt.Println(res.LastInsertId())
} 查看全部
下面的是一些常见的操作,如果需要写底层sql语句,使用频率极高,值得收藏。
/*
* @Author: 30daydo
* @FilePath: /go110/go-012/g012.go
* @Description: Go 数据库基本操作
*/
package main
import (
"database/sql"
"fmt"
"runtime"
_ "github.com/go-sql-driver/mysql"
)
/**
// 创建 user 表
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`name` varchar(50) COLLATE utf8mb4_general_ci NOT NULL COMMENT '姓名',
`age` int NOT NULL COMMENT '年龄',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户信息表'
**/
// 全局对象 db
var db *sql.DB
// 定义一个 user 结构体接收数据:
type user struct {
id int
age int
name string
}
// 始化数据库的函数
func initDB() (err error) {
// 构建连接的 dsn 格式是:"用户名:密码@tcp(IP:端口)/数据库?charset=utf8"
dsn := "user:password@tcp(127.0.0.1:3306)/sql_test?charset=utf8mb4&parseTime=True"
// 给全局变量赋值, 注意这里不要使用 :=
db, err = sql.Open("mysql", dsn)
if err != nil {
fmt.Println("初始化数据库失败")
return err
}
// 校验dsn是否正确
fmt.Println("尝试与数据库建立连接...")
err = db.Ping()
if err != nil {
fmt.Println("连接失败")
return err
}
fmt.Println("连接成功")
db.SetMaxOpenConns(2000) // 设置最大打开连接数
db.SetMaxIdleConns(10) // 设置最大空闲连接数
return nil
}
// 插入数据
func insertRow(name string, age int) int64 {
sqlStr := "INSERT INTO user(name, age) VALUES (?,?)"
ret, err := db.Exec(sqlStr, name, age)
if err != nil {
fmt.Printf("插入失败, err: %v\n", err)
return 0
}
// 新插入数据的 id
insertId, err := ret.LastInsertId()
if err != nil {
fmt.Printf("获取新插入数据的 ID 失败, err:%v\n", err)
return 0
}
fmt.Printf("插入成功, ID 为 %d.\n", insertId)
return insertId
}
// 查询单条数据记录
func queryRow(rowId int64) {
sqlStr := "SELECT id, name, age FROM user WHERE id = ?"
var u user
// 确保 QueryRow 之后调用 Scan 方法,释放持有的数据库链接
err := db.QueryRow(sqlStr, rowId).Scan(&u.id, &u.name, &u.age)
if err != nil {
fmt.Printf("未找到记录, 查询失败, err: %v\n", err)
return
}
fmt.Printf("查询数据成功, id: %d name: %s age: %d \n", u.id, u.name, u.age)
}
// 更新数据
func updateRow(rowId int64, newAge int) {
sqlStr := "UPDATE user SET age=? WHERE id = ?"
ret, err := db.Exec(sqlStr, newAge, rowId)
if err != nil {
fmt.Printf("更新失败 , err:%v\n", err)
return
}
// 操作影响的行数
n, err := ret.RowsAffected()
if err != nil {
fmt.Printf("获取影响函数失败, err: %v\n", err)
return
}
fmt.Printf("更新成功, 影响行数为: %d\n", n)
}
// 删除数据
func deleteRow(rowId int64) {
sqlStr := "DELETE FROM user WHERE id = ?"
ret, err := db.Exec(sqlStr, rowId)
if err != nil {
fmt.Printf("删除失败, err: %v\n", err)
return
}
n, err := ret.RowsAffected() // 操作影响的行数
if err != nil {
fmt.Printf("获取影响函数失败, err: %v\n", err)
return
}
fmt.Printf("删除成功, 影响行数为: %d\n", n)
}
// 查询多行
func queryMultiRow() {
sqlStr := "SELECT id, name, age FROM user WHERE id > ?"
rows, err := db.Query(sqlStr, 0)
if err != nil {
fmt.Printf("查询失败, err:%v\n", err)
return
}
// 重要:关闭 rows, 释放持有的数据库链接
defer rows.Close()
// 循环读取结果集中的数据
for rows.Next() {
var u user
err := rows.Scan(&u.id, &u.name, &u.age)
if err != nil {
fmt.Printf("查询多行数据失败, err:%v\n", err)
return
}
fmt.Printf("当前数据 id: %d name: %s age: %d\n", u.id, u.name, u.age)
}
}
func main() {
// 使用内置函数打印
println("Hello", "菜鸟实战")
// 初始化数据库
initDB()
// 插入数据
var id1 = insertRow("唐遇春", 17)
var id2 = insertRow("冯显", 38)
var id3 = insertRow("花千里", 20)
// 查询多行数据
queryMultiRow()
// 更新数据
updateRow(id2, 35)
// 查询单行数据
queryRow(id2)
// 删除数据
deleteRow(id1)
// 查询多行数据
queryMultiRow()
queryRow(id3)
// 当前版本
fmt.Printf("版本: %s \n", runtime.Version())
}
当然,上面的语句也可以不用Prepare的写法,直接插入进去:
func insertDirect() {
db, err := sql.Open("mysql",
"username:password@tcp(127.0.0.1:3306)/test_db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
sql := "INSERT INTO user(id, name, pwd) VALUES(?, ?, ?)"
res, err := db.Exec(sql, 13, "Jobs", "444555")
checkErr(err)
fmt.Println(res.LastInsertId())
}
golang 插入redis 集合,并判断元素是否存在
李魔佛 发表了文章 • 0 个评论 • 899 次浏览 • 2022-06-20 17:26
1. "server/service" 是当前的报名
2. 用的go-redis这个库
判断元素是否在集合中:
conn.SIsMember("User", sign).Result()
完整代码:
package cache
import (
"server/service"
"fmt"
"github.com/go-redis/redis"
)
type Cache struct {
conn *redis.Client
}
func (this *Cache) CacheInit() {
this.connect()
}
func (this *Cache) connect() {
conf := service.ReadRedisConfig()
this.conn = redis.NewClient(&redis.Options{
Addr: conf.Addr,
Password: conf.Password,
DB: conf.DB,
})
}
func (this *Cache) Get(id string) (string, bool) {
result, err := this.conn.Get(id).Result()
if err != nil {
fmt.Println(err)
return "", false
}
return result, true
}
func (this *Cache) Set(id string, content string) bool {
_, err := this.conn.Set(id, content, 0).Result()
if err != nil {
fmt.Println(err)
return false
} else {
return true
}
}
func (this *Cache) CheckUserExist(sign string) bool {
result, err := this.conn.SIsMember("User", sign).Result()
if err != nil {
fmt.Println(err)
return false
}
return result
}
func (this *Cache) AddUser(name string) bool {
_, err := this.conn.SAdd("User", name).Result()
if err != nil {
fmt.Println(err)
return false
} else {
return true
}
}
github地址:
https://github.com/Rockyzsu/BondInfoServer.git
查看全部
1. "server/service" 是当前的报名
2. 用的go-redis这个库
判断元素是否在集合中:
conn.SIsMember("User", sign).Result()
完整代码:
package cache
import (
"server/service"
"fmt"
"github.com/go-redis/redis"
)
type Cache struct {
conn *redis.Client
}
func (this *Cache) CacheInit() {
this.connect()
}
func (this *Cache) connect() {
conf := service.ReadRedisConfig()
this.conn = redis.NewClient(&redis.Options{
Addr: conf.Addr,
Password: conf.Password,
DB: conf.DB,
})
}
func (this *Cache) Get(id string) (string, bool) {
result, err := this.conn.Get(id).Result()
if err != nil {
fmt.Println(err)
return "", false
}
return result, true
}
func (this *Cache) Set(id string, content string) bool {
_, err := this.conn.Set(id, content, 0).Result()
if err != nil {
fmt.Println(err)
return false
} else {
return true
}
}
func (this *Cache) CheckUserExist(sign string) bool {
result, err := this.conn.SIsMember("User", sign).Result()
if err != nil {
fmt.Println(err)
return false
}
return result
}
func (this *Cache) AddUser(name string) bool {
_, err := this.conn.SAdd("User", name).Result()
if err != nil {
fmt.Println(err)
return false
} else {
return true
}
}
github地址:
https://github.com/Rockyzsu/BondInfoServer.git
在中国网络环境下获取Golang.org上的Golang Packages
李魔佛 发表了文章 • 0 个评论 • 830 次浏览 • 2022-06-16 10:26
背景
目前在中国网络环境下无法访问Golang.org。
问题
不能运行go get golang.org/x/XX来获取Golang packages。
解决方案
方案 A: 使用github 上的镜像
获取Golang Package在github镜像上的路径: golang.org/x/PATH_TO_PACKAGE --> github.com/golang/PATH_TO_PACKAGE.
// Ex:
golang.org/x/net/context --> github.com/golang/net/context
运行go get来安装github镜像的Golang packages。
// Ex:
go get github.com/golang/net/context
你会碰到如下错误提示:
package github.com/golang/net/context:
code in directory /go/src/github.com/golang/net/context
expects import "golang.org/x/net/context"
忽略错误。 Golang的Package的源代码已经成功下载于:
$GOPATH/src/github.com/golang/PATH_TO_PACKAGE.
复制 $GOPATH/src/github.com/golang/PATH_TO_PACKAGE 到 $GOPATH/src/golang.org/x/PATH_TO_PACKAGE.
// Ex:
mkdir $GOPATH/src/golang.org/x -p
cp $GOPATH/src/github.com/golang/net $GOPATH/src/golang.org/x/ -rf
运行 go build 来编译。
方案 B: 使用第三方网站 - https://gopm.io/download
输入包路径即可下载zip文件。 查看全部
在中国网络环境下获取Golang.org上的Golang Packages
背景
目前在中国网络环境下无法访问Golang.org。
问题
不能运行go get golang.org/x/XX来获取Golang packages。
解决方案
方案 A: 使用github 上的镜像
获取Golang Package在github镜像上的路径: golang.org/x/PATH_TO_PACKAGE --> github.com/golang/PATH_TO_PACKAGE.
// Ex:
golang.org/x/net/context --> github.com/golang/net/context
运行go get来安装github镜像的Golang packages。
// Ex:
go get github.com/golang/net/context
你会碰到如下错误提示:
package github.com/golang/net/context:
code in directory /go/src/github.com/golang/net/context
expects import "golang.org/x/net/context"
忽略错误。 Golang的Package的源代码已经成功下载于:
$GOPATH/src/github.com/golang/PATH_TO_PACKAGE.
复制 $GOPATH/src/github.com/golang/PATH_TO_PACKAGE 到 $GOPATH/src/golang.org/x/PATH_TO_PACKAGE.
// Ex:
mkdir $GOPATH/src/golang.org/x -p
cp $GOPATH/src/github.com/golang/net $GOPATH/src/golang.org/x/ -rf
运行 go build 来编译。
方案 B: 使用第三方网站 - https://gopm.io/download
输入包路径即可下载zip文件。
golang gin ajax post 前端与后端的正确写法
李魔佛 发表了文章 • 0 个评论 • 1356 次浏览 • 2022-06-08 18:42
前端是一个页面html页面
<script type="text/javascript">
var submitBTN = document.getElementById("url_update");
submitBTN.onclick = function (event) {
// 注意这里是 onclick 函数
console.log("click");
$.ajax({
url: "/update-site1",
type: "POST",
data: {value:1},
cache: false,
contentType: "application/x-www-form-urlencoded",
success: function (data) {
console.log(data);
if (data.code !== 0) {
alert('更新失败')
} else {
new_str = data.res + " " + data.count
$("#txt_content").val(new_str);
alert('更新资源成功!')
}
},
fail: function (data) {
alert("更新失败!");
}
});
$.ajax({
url: "/update-site1",
type: "POST",
data: {value:2},
cache: false,
contentType: "application/x-www-form-urlencoded",
success: function (data) {
console.log(data);
if (data.code !== 0) {
alert('更新失败')
} else {
new_str = data.res + " " + data.count
$("#txt_content").val(new_str);
alert('更新资源成功!')
}
},
fail: function (data) {
alert("更新失败!");
}
})
}
</script>
效果大体上这样的:
有几个按钮,然后每个按钮绑定一个点击事件
submitBTN.onclick = function (event) {
.....
同上面代码
然后在代码里面执行post操作,使用的是ajax封装的方法:
注意,contentType用下面的:
contentType: "application/x-www-form-urlencoded",
还有不要把
processData: false,这个设置为false,否则gin的后端解析不到数据
写完前端之后,就去后端
路由方法:
绑定上面的url update-site1
router.POST("/update-site1", controllers.BaiduSite1)
然后就是实现
controllers.BaiduSite1 这个方法:
func BaiduSite1(ctx *gin.Context) {
if ctx.Request.Method == "POST" {
value := ctx.PostForm("value")
fmt.Println(value)
int_value, err := strconv.Atoi(value)
if err != nil {
ctx.JSON(http.StatusOK, gin.H{
"code": 1,
"res": "",
"count": 0,
})
return
}
res, count := webmaster.PushProcess(1, int_value)
ctx.JSON(http.StatusOK, gin.H{
"code": 0,
"res": res,
"count": count,
})
}
}
获取ajax里面的字段,
使用:context 中的PostForm方法
value := ctx.PostForm("value")
剩下的就是一些常规的操作方法
最后需要设置json的返回数据
ctx.JSON(http.StatusOK, gin.H{
"code": 0,
"res": res,
"count": count,
完整代码可以到公众号里面获取:
查看全部
前端是一个页面html页面
<script type="text/javascript">
var submitBTN = document.getElementById("url_update");
submitBTN.onclick = function (event) {
// 注意这里是 onclick 函数
console.log("click");
$.ajax({
url: "/update-site1",
type: "POST",
data: {value:1},
cache: false,
contentType: "application/x-www-form-urlencoded",
success: function (data) {
console.log(data);
if (data.code !== 0) {
alert('更新失败')
} else {
new_str = data.res + " " + data.count
$("#txt_content").val(new_str);
alert('更新资源成功!')
}
},
fail: function (data) {
alert("更新失败!");
}
});
$.ajax({
url: "/update-site1",
type: "POST",
data: {value:2},
cache: false,
contentType: "application/x-www-form-urlencoded",
success: function (data) {
console.log(data);
if (data.code !== 0) {
alert('更新失败')
} else {
new_str = data.res + " " + data.count
$("#txt_content").val(new_str);
alert('更新资源成功!')
}
},
fail: function (data) {
alert("更新失败!");
}
})
}
</script>
效果大体上这样的:
有几个按钮,然后每个按钮绑定一个点击事件
submitBTN.onclick = function (event) {
.....
同上面代码
然后在代码里面执行post操作,使用的是ajax封装的方法:
注意,contentType用下面的:
contentType: "application/x-www-form-urlencoded",
还有不要把
processData: false,这个设置为false,否则gin的后端解析不到数据
写完前端之后,就去后端
路由方法:
绑定上面的url update-site1
router.POST("/update-site1", controllers.BaiduSite1)
然后就是实现
controllers.BaiduSite1 这个方法:
func BaiduSite1(ctx *gin.Context) {
if ctx.Request.Method == "POST" {
value := ctx.PostForm("value")
fmt.Println(value)
int_value, err := strconv.Atoi(value)
if err != nil {
ctx.JSON(http.StatusOK, gin.H{
"code": 1,
"res": "",
"count": 0,
})
return
}
res, count := webmaster.PushProcess(1, int_value)
ctx.JSON(http.StatusOK, gin.H{
"code": 0,
"res": res,
"count": count,
})
}
}
获取ajax里面的字段,
使用:context 中的PostForm方法
value := ctx.PostForm("value")
剩下的就是一些常规的操作方法
最后需要设置json的返回数据
ctx.JSON(http.StatusOK, gin.H{
"code": 0,
"res": res,
"count": count,
完整代码可以到公众号里面获取:

docker部署golang应用 无法下载第三方包 解决办法
李魔佛 发表了文章 • 0 个评论 • 1238 次浏览 • 2022-03-14 14:43
ENV GOPROXY https://goproxy.cn
RUN go mod download
RUN go build main.go
ENV GOPROXY https://goproxy.cn
RUN go mod download
RUN go build main.go
性能测试: flask WSGI vs 异步 ASGI vs tornodo vs Golang Gin
李魔佛 发表了文章 • 0 个评论 • 2342 次浏览 • 2022-01-12 10:58
测试命令:
ab -kc 1000 -n 4000 http://127.0.0.1:5000/
代码最精简:
flask wsgi:from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run(host='0.0.0.0')
得到的结果:
ASGI的代码:async def app(scope, receive, send):
await send({
'type': 'http.response.start',
'status': 200,
'headers': [
[b'content-type', b'text/html']
]
})
await send({
'type': 'http.response.body',
'body': b'Hello This is server running',
'more_body': False
})
运行命令:
uvicorn --host 0.0.0.0 simple_asgi:app
得到的结果:
python的tornado
from tornado import ioloop
from tornado import web
class Homepage(web.RequestHandler):
def get(self):
print('get method')
self.write("This is tornado server")
if __name__ == '__main__':
app = web.Application([
("/",Homepage),
])
app.listen(8888)
ioloop.IOLoop.current().start()
Goland的gin package main
import "github.com/gin-gonic/gin"
// 测试专用
func main() {
r := gin.Default()
r.GET("/index", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "Working"})
})
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "Working"})
})
r.Run()
}
通过requests per second 每秒的请求数:
flask : 1000
uvicorn: 2000
tornoda:3000
go gin:4000
所以综合测试结果,flask的性能最烂,go gin的性能最好。差了4倍。
转载请注明出处:
http://www.30daydo.com/article/44336
查看全部
测试命令:
ab -kc 1000 -n 4000 http://127.0.0.1:5000/
代码最精简:
flask wsgi:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run(host='0.0.0.0')
得到的结果:

ASGI的代码:
async def app(scope, receive, send):
await send({
'type': 'http.response.start',
'status': 200,
'headers': [
[b'content-type', b'text/html']
]
})
await send({
'type': 'http.response.body',
'body': b'Hello This is server running',
'more_body': False
})
运行命令:
uvicorn --host 0.0.0.0 simple_asgi:app
得到的结果:

python的tornado
from tornado import ioloop
from tornado import web
class Homepage(web.RequestHandler):
def get(self):
print('get method')
self.write("This is tornado server")
if __name__ == '__main__':
app = web.Application([
("/",Homepage),
])
app.listen(8888)
ioloop.IOLoop.current().start()

Goland的gin
package main
import "github.com/gin-gonic/gin"
// 测试专用
func main() {
r := gin.Default()
r.GET("/index", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "Working"})
})
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "Working"})
})
r.Run()
}

通过requests per second 每秒的请求数:
flask : 1000
uvicorn: 2000
tornoda:3000
go gin:4000
所以综合测试结果,flask的性能最烂,go gin的性能最好。差了4倍。
转载请注明出处:
http://www.30daydo.com/article/44336
ubuntu goland破解激活教程
李魔佛 发表了文章 • 0 个评论 • 3736 次浏览 • 2022-01-05 13:08
ubuntu下的goland可以直接到官网下载。
或者在自带的software center。
不过goland只能试用一个月,一个月后只能要激活。
所以有一个reset插件,可以每次开启goland的时候把激活日期重置,往后推一个月。
只需要打开goland,然后把插件拖进去goland的界面即可。
插件获取方式:
关注公众号:
30天尝试新事情
后台回复:goland激活
即可 查看全部
ubuntu下的goland可以直接到官网下载。
或者在自带的software center。
不过goland只能试用一个月,一个月后只能要激活。
所以有一个reset插件,可以每次开启goland的时候把激活日期重置,往后推一个月。
只需要打开goland,然后把插件拖进去goland的界面即可。




插件获取方式:
关注公众号:
30天尝试新事情

后台回复:goland激活
即可
ubuntu(centos)下golang下载libxml2 报错信息, go 安装libxml2
李魔佛 发表了文章 • 0 个评论 • 1123 次浏览 • 2021-12-29 23:20
# pkg-config --cflags -- libxml-2.0 Package libxml-2.0 was not found in the pkg-config search path.
Perhaps you should add the directory containing `libxml-2.0.pc' to the PKG_CONFIG_PATH environment variable
No package 'libxml-2.0' found pkg-config: exit status 1
因为系统少了个libxml2 开发包:
使用以下命令即可修复:sudo apt install libxml2-dev
如果是centos的话,安装命令:yum install libxml2
yum install libxml2-devel
注意是 libxml2-devel !
别用那种下载源码编译的方法,能用yum就用yum,否则弄得系统一堆依赖问题。 查看全部
$ go get -u github.com/lestrrat-go/libxml2
# pkg-config --cflags -- libxml-2.0 Package libxml-2.0 was not found in the pkg-config search path.
Perhaps you should add the directory containing `libxml-2.0.pc' to the PKG_CONFIG_PATH environment variable
No package 'libxml-2.0' found pkg-config: exit status 1
因为系统少了个libxml2 开发包:
使用以下命令即可修复:
sudo apt install libxml2-dev
如果是centos的话,安装命令:
yum install libxml2
yum install libxml2-devel
注意是 libxml2-devel !
别用那种下载源码编译的方法,能用yum就用yum,否则弄得系统一堆依赖问题。
现在很多公众号都是粗制滥造, 代码也没经过验证 就贴上来害人
李魔佛 发表了文章 • 0 个评论 • 1059 次浏览 • 2021-12-27 11:52
你说函数签名的Counter写错就算了. 但是返回的也是一个指针呀......
正确写法
func NewNotSafeCounter() *NotSafeCounter {
return &NotSafeCounter{0}
}
查看全部

你说函数签名的Counter写错就算了. 但是返回的也是一个指针呀......
正确写法
func NewNotSafeCounter() *NotSafeCounter {
return &NotSafeCounter{0}
}
golang json Unmarshal 无法修改结构体的值。传入指针
李魔佛 发表了文章 • 0 个评论 • 1392 次浏览 • 2021-12-20 12:59
{ "username": "root", "password": "123456", "host": "1.1.1.1.", "port": 3306, "db": "admin" }
然后我的定义的结构体:
type T struct {
username string `json:"username"`
password string `json:"password"`
host string `json:"host"`
port int `json:"port"`
db string `json:"db"`
}
然后程序里面解析json的代码:var t T
data, err := ioutil.ReadFile(filename)
fmt.Println("read from file")
//fmt.Println(string(data))
if err != nil {
fmt.Println("in error")
fmt.Println(err)
return err
}
err = json.Unmarshal(data, &t)
if err != nil {
fmt.Println("error ")
fmt.Println(err)
return err
}
fmt.Println("outpout ")
fmt.Printf("%v\n", t)
fmt.Println(t)
发现是无法把t的值修改为json文件里面的值,最后的记过输出,还是一个零值的结果体。
后面知道问题所在了,如果定义的结构体的首字母小写的时候,包外的反射是无法修改结构体的值的,也就是只能只读。
所以只需要把结构体的首字母改为大写,问题就可以解决了。type T struct {
Username string `json:"username"`
Password string `json:"password"`
Host string `json:"host"`
Port int `json:"port"`
Db string `json:"db"`
}
json文件里面不用修改,因为
Unmarshal映射的时候可以适配大小写。
查看全部
{ "username": "root", "password": "123456", "host": "1.1.1.1.", "port": 3306, "db": "admin" }
然后我的定义的结构体:
type T struct {
username string `json:"username"`
password string `json:"password"`
host string `json:"host"`
port int `json:"port"`
db string `json:"db"`
}
然后程序里面解析json的代码:
var t T
data, err := ioutil.ReadFile(filename)
fmt.Println("read from file")
//fmt.Println(string(data))
if err != nil {
fmt.Println("in error")
fmt.Println(err)
return err
}
err = json.Unmarshal(data, &t)
if err != nil {
fmt.Println("error ")
fmt.Println(err)
return err
}
fmt.Println("outpout ")
fmt.Printf("%v\n", t)
fmt.Println(t)
发现是无法把t的值修改为json文件里面的值,最后的记过输出,还是一个零值的结果体。
后面知道问题所在了,如果定义的结构体的首字母小写的时候,包外的反射是无法修改结构体的值的,也就是只能只读。
所以只需要把结构体的首字母改为大写,问题就可以解决了。
type T struct {
Username string `json:"username"`
Password string `json:"password"`
Host string `json:"host"`
Port int `json:"port"`
Db string `json:"db"`
}
json文件里面不用修改,因为
Unmarshal映射的时候可以适配大小写。
为什么现在还有那么多在线的gonlang 字符串生成json struct的网站? Goland IDE一个快捷方式帮你搞定
李魔佛 发表了文章 • 0 个评论 • 920 次浏览 • 2021-12-20 01:00
}
在出现的generate from json的页面,把json的字符串输入进去。
IDE即可帮你转换为对应的结构体了。 根本就没有在线IDE什么事情了。
}
在出现的generate from json的页面,把json的字符串输入进去。
IDE即可帮你转换为对应的结构体了。 根本就没有在线IDE什么事情了。
golang根据不同返回解析不同结构的json
李魔佛 发表了文章 • 0 个评论 • 1149 次浏览 • 2021-12-20 00:35
{"type":"a_number", "data":{"somenumber":1234}}
{"type":"b_string", "data":{"somestring":"a string", "anotherstring": "a second string"}}`
如何解析上面返回的json结构体
答:json.RawMessage
type Head struct {
Type string `json:"type"`
Data json.RawMessage `json:"data"`
}
var msg Head
json.Unmarshal([]byte(jsonString), &msg)
switch msg.Type {
case "a_number":
var detail A
json.Unmarshal([]byte(msg.Data),&detail)
fmt.Println(detail.SomeNumber)
case "b_string":
var detail B
json.Unmarshal([]byte(msg.Data),&detail)
fmt.Println(detail.SomeString)
default:
fmt.Printf("I don't know about type %s!\n", msg.Type)
}
就可以解析上面的不规则的结构体了。
查看全部
// 数据源
{"type":"a_number", "data":{"somenumber":1234}}
{"type":"b_string", "data":{"somestring":"a string", "anotherstring": "a second string"}}`
如何解析上面返回的json结构体
答:json.RawMessage
type Head struct {
Type string `json:"type"`
Data json.RawMessage `json:"data"`
}
var msg Head
json.Unmarshal([]byte(jsonString), &msg)
switch msg.Type {
case "a_number":
var detail A
json.Unmarshal([]byte(msg.Data),&detail)
fmt.Println(detail.SomeNumber)
case "b_string":
var detail B
json.Unmarshal([]byte(msg.Data),&detail)
fmt.Println(detail.SomeString)
default:
fmt.Printf("I don't know about type %s!\n", msg.Type)
}
就可以解析上面的不规则的结构体了。
30天学会Golang
马化云 发表了文章 • 0 个评论 • 1127 次浏览 • 2021-12-04 12:20
附github目录图以及github地址
https://github.com/Rockyzsu/GolangLearning
同时欢迎关注公众号: 30天尝试新事情
查看全部
附github目录图以及github地址
https://github.com/Rockyzsu/GolangLearning

同时欢迎关注公众号: 30天尝试新事情

golang 的sync.Cond Wait 为什么要先Lock之后才能Wait ?
李魔佛 发表了文章 • 0 个评论 • 1252 次浏览 • 2021-11-24 00:09
fmt.Println("waiting on broadcast")
fmt.Printf("Lock %d\n", id)
con.L.Lock() //需要现先lock
con.Wait()
fn()
defer con.L.Unlock()
}
如果直接Wait,会报错,死锁
然后看了看源码:
原来Wait函数里面,会先Unlock一次,再去跑runtime通知。
也就是你不Lock一下,进入到Wait函数就会一直锁住。
查看全部
cannot install, GOBIN must be an absolute path
李魔佛 发表了文章 • 0 个评论 • 1845 次浏览 • 2021-11-22 22:32
把GOPATH替换为完整的路径,比如C:\User\Admin\go\bin 即可解决问题。
原创文章,转载请注明出处:
http://30daydo.com/article/44290
查看全部
把GOPATH替换为完整的路径,比如C:\User\Admin\go\bin 即可解决问题。
原创文章,转载请注明出处:
http://30daydo.com/article/44290
gin can not run reasons: c.engine.AppEngine undefined
李魔佛 发表了文章 • 0 个评论 • 1050 次浏览 • 2021-11-22 22:29
C:\Users\xda\go\pkg\mod\github.com\gin-gonic\gin@v1.7.5\context.go:735:13: c.engine.AppEngine undefined (type *Engine ha
s no field or method AppEngine)
C:\Users\xda\go\pkg\mod\github.com\gin-gonic\gin@v1.7.5\gin.go:154:3: unknown field 'UseRawPath' in struct literal of ty
pe Engine
C:\Users\xda\go\pkg\mod\github.com\gin-gonic\gin@v1.7.5\gin.go:156:3: unknown field 'UnescapePathValues' in struct liter
al of type Engine
C:\Users\xda\go\pkg\mod\github.com\gin-gonic\gin@v1.7.5\gin.go:508:11: engine.UseRawPath undefined (type *Engine has no
field or method UseRawPath)
C:\Users\xda\go\pkg\mod\github.com\gin-gonic\gin@v1.7.5\gin.go:510:20: engine.UnescapePathValues undefined (type *Engine
has no field or method UnescapePathValues)
源码:package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
// 1.创建路由
r := gin.Default()
// 2.绑定路由规则,执行的函数
// gin.Context,封装了request和response
r.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "hello World!")
})
// 3.监听端口,默认在8080
// Run("里面不指定端口号默认为8080")
r.Run(":8000")
}
版本兼容性问题,降级到 gin@1.7.2 即可解决问题。
当前最新的版本为1.7.5
降级方法:
go get github.com/gin-gonic/gin@v1.7.2
原创文章,转载请注明出处:
http://30daydo.com/article/44289
查看全部
# github.com/gin-gonic/gin
C:\Users\xda\go\pkg\mod\github.com\gin-gonic\gin@v1.7.5\context.go:735:13: c.engine.AppEngine undefined (type *Engine ha
s no field or method AppEngine)
C:\Users\xda\go\pkg\mod\github.com\gin-gonic\gin@v1.7.5\gin.go:154:3: unknown field 'UseRawPath' in struct literal of ty
pe Engine
C:\Users\xda\go\pkg\mod\github.com\gin-gonic\gin@v1.7.5\gin.go:156:3: unknown field 'UnescapePathValues' in struct liter
al of type Engine
C:\Users\xda\go\pkg\mod\github.com\gin-gonic\gin@v1.7.5\gin.go:508:11: engine.UseRawPath undefined (type *Engine has no
field or method UseRawPath)
C:\Users\xda\go\pkg\mod\github.com\gin-gonic\gin@v1.7.5\gin.go:510:20: engine.UnescapePathValues undefined (type *Engine
has no field or method UnescapePathValues)
源码:
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
// 1.创建路由
r := gin.Default()
// 2.绑定路由规则,执行的函数
// gin.Context,封装了request和response
r.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "hello World!")
})
// 3.监听端口,默认在8080
// Run("里面不指定端口号默认为8080")
r.Run(":8000")
}
版本兼容性问题,降级到 gin@1.7.2 即可解决问题。
当前最新的版本为1.7.5
降级方法:
go get github.com/gin-gonic/gin@v1.7.2
原创文章,转载请注明出处:
http://30daydo.com/article/44289
golang文件操作之 移动文件
李魔佛 发表了文章 • 0 个评论 • 3678 次浏览 • 2021-11-21 20:35
package main
import (
"log"
"os"
)
func main() {
oldLocation := "/var/www/html/test.txt"
newLocation := "/var/www/html/src/test.txt"
err := os.Rename(oldLocation, newLocation)
if err != nil {
log.Fatal(err)
}
}
原创文章,转载请注明出处:
http://30daydo.com/article/44288
查看全部
package main
import (
"log"
"os"
)
func main() {
oldLocation := "/var/www/html/test.txt"
newLocation := "/var/www/html/src/test.txt"
err := os.Rename(oldLocation, newLocation)
if err != nil {
log.Fatal(err)
}
}
原创文章,转载请注明出处:
http://30daydo.com/article/44288