golang
github.com/lestrrat-go/libxml2 这个xpath包在windows下无法使用
Golang • 马化云 发表了文章 • 0 个评论 • 1070 次浏览 • 2023-08-18 12:11
(base) PS C:\git\qiniu_web_gin> go run .\main.go
# github.com/lestrrat-go/libxml2/xpath
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:40:35: undefined: clib.XMLXPathObjectType
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:45:14: undefined: clib.XMLXPathObjectFloat64
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:50:14: undefined: clib.XMLXPathObjectBool
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:74:18: undefined: clib.XMLXPathObjectNodeList
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:91:18: undefined: clib.XMLXPathObjectNodeList
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:124:7: undefined: clib.XMLXPathFreeObject
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:129:19: undefined: clib.XMLXPathCompile
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:149:7: undefined: clib.XMLXPathFreeCompExpr
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:163:22: undefined: clib.XMLXPathNewContext
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:179:14: undefined: clib.XMLXPathContextSetContextNode
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:179:14: too many errors
(base) PS C:\git\qiniu_web_gin> go get github.com/lestrrat-go/libxml2
(base) PS C:\git\qiniu_web_gin>
然后到作者的官网上逛了一圈,出现这个问题,需要自己编译一个libxml2 windows版本的
官方给出的是源码:
libxml2-2.11.5-win-build Latest
Corresponding to official release version 2.11.5.
然后编译C的源码,需要很多的工具链和依赖。
windows至少需要Visual Studio, 不是vs code呢。 Visual Studio安装完,至少要被占用10GB的空间。
libxml2 + iconv + msvc 在windows下生成使用库
为了跨平台的解析xml,偶然获得Linux下比较好用的一个xml的解析库libxml2,使用起来确实比较简单,方便;但移植到windows下后发下使用上存在问题:
无法解析格式位GB2312类型的XML文件,但由于一些外部因素,Windows下必须使用GB2312格式
在网上查看了诸多教程,有很多编译生成libxml2库的文章,但都不支持iconv,仔细阅读README后,终于生成了可用的libxml2.lib库,记录下来备用
操作系统:windows 7 x64
版本:libiconv-1.15, libxml2 Github版本
Visual Studio版本:vs2015
Cygwin:x64
以下操作皆为生成x64位库,32位的基本类似,可以查看具体的README。
所以想想还是算了,直接切换到ubuntu开发了。惹不起,还躲不起吗 :(
我:@lestrrat Hi, is that mean it can't work on windows if i dont build it with visual studio or cgywin like?
作者:It's the same as when you are building a C program. You build in the same arch/os as the where you intend to run the program.
我:Thanks a lot. Instsall vs environment taks lots of time, so i switch to the ubuntu to "quick fix this issue" :(
逃-》
查看全部
(base) PS C:\git\qiniu_web_gin> go run .\main.go
# github.com/lestrrat-go/libxml2/xpath
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:40:35: undefined: clib.XMLXPathObjectType
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:45:14: undefined: clib.XMLXPathObjectFloat64
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:50:14: undefined: clib.XMLXPathObjectBool
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:74:18: undefined: clib.XMLXPathObjectNodeList
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:91:18: undefined: clib.XMLXPathObjectNodeList
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:124:7: undefined: clib.XMLXPathFreeObject
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:129:19: undefined: clib.XMLXPathCompile
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:149:7: undefined: clib.XMLXPathFreeCompExpr
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:163:22: undefined: clib.XMLXPathNewContext
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:179:14: undefined: clib.XMLXPathContextSetContextNode
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:179:14: too many errors
(base) PS C:\git\qiniu_web_gin> go get github.com/lestrrat-go/libxml2
(base) PS C:\git\qiniu_web_gin>
然后到作者的官网上逛了一圈,出现这个问题,需要自己编译一个libxml2 windows版本的
官方给出的是源码:
libxml2-2.11.5-win-build Latest
Corresponding to official release version 2.11.5.
然后编译C的源码,需要很多的工具链和依赖。
windows至少需要Visual Studio, 不是vs code呢。 Visual Studio安装完,至少要被占用10GB的空间。
libxml2 + iconv + msvc 在windows下生成使用库
为了跨平台的解析xml,偶然获得Linux下比较好用的一个xml的解析库libxml2,使用起来确实比较简单,方便;但移植到windows下后发下使用上存在问题:
无法解析格式位GB2312类型的XML文件,但由于一些外部因素,Windows下必须使用GB2312格式
在网上查看了诸多教程,有很多编译生成libxml2库的文章,但都不支持iconv,仔细阅读README后,终于生成了可用的libxml2.lib库,记录下来备用
操作系统:windows 7 x64
版本:libiconv-1.15, libxml2 Github版本
Visual Studio版本:vs2015
Cygwin:x64
以下操作皆为生成x64位库,32位的基本类似,可以查看具体的README。
所以想想还是算了,直接切换到ubuntu开发了。惹不起,还躲不起吗 :(
我:@lestrrat Hi, is that mean it can't work on windows if i dont build it with visual studio or cgywin like?
作者:It's the same as when you are building a C program. You build in the same arch/os as the where you intend to run the program.
我:Thanks a lot. Instsall vs environment taks lots of time, so i switch to the ubuntu to "quick fix this issue" :(
逃-》
golang执行系统shell命令,并获取返回内容
Golang • 马化云 发表了文章 • 0 个评论 • 1617 次浏览 • 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(*) 的写法
Golang • 马化云 发表了文章 • 0 个评论 • 1566 次浏览 • 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操作 保存这篇文章就足够了)
Golang • 马化云 发表了文章 • 0 个评论 • 1644 次浏览 • 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 集合,并判断元素是否存在
Golang • 李魔佛 发表了文章 • 0 个评论 • 1728 次浏览 • 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
Golang • 李魔佛 发表了文章 • 0 个评论 • 1652 次浏览 • 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 前端与后端的正确写法
Golang • 李魔佛 发表了文章 • 0 个评论 • 2510 次浏览 • 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应用 无法下载第三方包 解决办法
Golang • 李魔佛 发表了文章 • 0 个评论 • 2048 次浏览 • 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
ubuntu(centos)下golang下载libxml2 报错信息, go 安装libxml2
Golang • 李魔佛 发表了文章 • 0 个评论 • 1960 次浏览 • 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,否则弄得系统一堆依赖问题。
REST ful API的规范 delete方法不建议在body放入数据
网络 • 李魔佛 发表了文章 • 0 个评论 • 2260 次浏览 • 2021-12-27 14:58
因为资源的唯一性,所以就没必要再在body里面放入其他的数据了.
什么? 通过uri不能确定资源的唯一? 那么你这个设计就不是REST规范了.
那PUT这些操作也无法准确更新资源了.
因为资源的唯一性,所以就没必要再在body里面放入其他的数据了.
什么? 通过uri不能确定资源的唯一? 那么你这个设计就不是REST规范了.
那PUT这些操作也无法准确更新资源了.
golang的时间格式化 做法有点像格力手机的开机画面是董小姐
闲聊 • 李魔佛 发表了文章 • 0 个评论 • 1687 次浏览 • 2021-12-20 13:01
过去用java,python,php,等语言,将一个时间格式化成一个字符串都是用“yyy-MM-dd hh:mm:ss”之类的方法,golang 的格式化方法真令我大开眼界
先看官方文档说明:
func (Time) Format
func (t Time) Format(layout string) string
Format returns a textual representation of the time value formatted according to layout, which defines the format by showing how the reference time, defined to be
Mon Jan 2 15:04:05 -0700 MST 2006
would be displayed if it were the value; it serves as an example of the desired output. The same display rules will then be applied to the time value. Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard and convenient representations of the reference time. For more information about the formats and the definition of the reference time, see the documentation for ANSIC and the other constants defined by this package.
下面给个代码:
fmt.Println(time.Now().Format("2006-01-02 150405"))
要注意那时间,只能是2006-01-02 15:04:05分,其它的时间都不行,真是够绝。
做法有点像格力手机的开机画面是董小姐。
用个语言还得记住你golang的生日?? 查看全部
过去用java,python,php,等语言,将一个时间格式化成一个字符串都是用“yyy-MM-dd hh:mm:ss”之类的方法,golang 的格式化方法真令我大开眼界
先看官方文档说明:
func (Time) Format
func (t Time) Format(layout string) string
Format returns a textual representation of the time value formatted according to layout, which defines the format by showing how the reference time, defined to be
Mon Jan 2 15:04:05 -0700 MST 2006
would be displayed if it were the value; it serves as an example of the desired output. The same display rules will then be applied to the time value. Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard and convenient representations of the reference time. For more information about the formats and the definition of the reference time, see the documentation for ANSIC and the other constants defined by this package.
下面给个代码:
fmt.Println(time.Now().Format("2006-01-02 150405"))
要注意那时间,只能是2006-01-02 15:04:05分,其它的时间都不行,真是够绝。
做法有点像格力手机的开机画面是董小姐。
用个语言还得记住你golang的生日??
golang json Unmarshal 无法修改结构体的值。传入指针
Golang • 李魔佛 发表了文章 • 0 个评论 • 2226 次浏览 • 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映射的时候可以适配大小写。
golang根据不同返回解析不同结构的json
Golang • 李魔佛 发表了文章 • 0 个评论 • 1920 次浏览 • 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
Golang • 马化云 发表了文章 • 0 个评论 • 1850 次浏览 • 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 ?
Golang • 李魔佛 发表了文章 • 0 个评论 • 2145 次浏览 • 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
Golang • 李魔佛 发表了文章 • 0 个评论 • 2939 次浏览 • 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
Golang • 李魔佛 发表了文章 • 0 个评论 • 1806 次浏览 • 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文件操作之 移动文件
Golang • 李魔佛 发表了文章 • 0 个评论 • 4874 次浏览 • 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
golang:为什么chan关闭了也无法接受到内容呢?
Golang • 李魔佛 发表了文章 • 0 个评论 • 1914 次浏览 • 2021-11-18 20:12
import "fmt"
func main() {
ch := make(chan int)
ch <- 1
close(ch)
n, ok := <-ch
if !ok {
fmt.Println("Error")
}
fmt.Println(n)
var input string
fmt.Scanln(&input)
}
实际程序死锁。
有人问,chan close后不会可以被读取到了吗?
但是实际程序运行到:
ch <- 1
这里, 已经被阻塞,导致报错,无法接下来的close操作。
加入打印信息:package main
import "fmt"
func main() {
ch := make(chan int)
fmt.Println("start")
ch <- 1
fmt.Println("next")
close(ch)
n, ok := <-ch
if !ok {
fmt.Println("Error")
}
fmt.Println(n)
var input string
fmt.Scanln(&input)
}
实际只打印到start, next那个已经不输出了。:!go run channel_close.go
start
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/home/admin/git/GolangLearning/helloworld/channel/channel_close.go:8 +0xa8
exit status 2
shell returned 1
正确的修改:package main
import "fmt"
func main() {
ch := make(chan int)
go func() {
fmt.Println("start")
ch <- 1
fmt.Println("next")
close(ch)
}()
n, ok := <-ch
if !ok {
fmt.Println("Error")
}
fmt.Println(n)
var input string
fmt.Scanln(&input)
}
创建了一个免费的Go知识星球社区,欢迎加入一起讨论吧
查看全部
package main
import "fmt"
func main() {
ch := make(chan int)
ch <- 1
close(ch)
n, ok := <-ch
if !ok {
fmt.Println("Error")
}
fmt.Println(n)
var input string
fmt.Scanln(&input)
}
实际程序死锁。
有人问,chan close后不会可以被读取到了吗?
但是实际程序运行到:
ch <- 1
这里, 已经被阻塞,导致报错,无法接下来的close操作。
加入打印信息:
package main
import "fmt"
func main() {
ch := make(chan int)
fmt.Println("start")
ch <- 1
fmt.Println("next")
close(ch)
n, ok := <-ch
if !ok {
fmt.Println("Error")
}
fmt.Println(n)
var input string
fmt.Scanln(&input)
}
实际只打印到start, next那个已经不输出了。
:!go run channel_close.go
start
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/home/admin/git/GolangLearning/helloworld/channel/channel_close.go:8 +0xa8
exit status 2
shell returned 1
正确的修改:
package main
import "fmt"
func main() {
ch := make(chan int)
go func() {
fmt.Println("start")
ch <- 1
fmt.Println("next")
close(ch)
}()
n, ok := <-ch
if !ok {
fmt.Println("Error")
}
fmt.Println(n)
var input string
fmt.Scanln(&input)
}
创建了一个免费的Go知识星球社区,欢迎加入一起讨论吧
go get 加 -u 和不加 -u 参数的区别
Golang • 李魔佛 发表了文章 • 0 个评论 • 1769 次浏览 • 2021-11-09 14:44
如果不加这个 -u 标记,执行 go get 一个已有的代码包,会发现命令什么都不执行。
只有加了 -u 标记,命令会去执行 git pull 命令拉取最新的代码包的最新版本,下载并安装。 查看全部
如果已经下载过一个代码包,但是这个代码包又有更新了,那么这时候可以直接用 -u 标记来更新本地的对应的代码包。
如果不加这个 -u 标记,执行 go get 一个已有的代码包,会发现命令什么都不执行。
只有加了 -u 标记,命令会去执行 git pull 命令拉取最新的代码包的最新版本,下载并安装。
golang中chan 无缓冲和 chan有缓冲 长度size设为1的区别
Golang • 低调的哥哥 发表了文章 • 0 个评论 • 3278 次浏览 • 2021-10-28 09:15
无缓冲情况下,一把数据放入chan,如果没有其他协程取数据,接下来的操作是阻塞的
而在size=1的情况下, 第一个数据放入chan后,并不会马上阻塞,接下来的操作还是可以进行的。
看下面的代码 f1和f2的区别
package main
import "time"
func f1() {
ch := make(chan int) // no buffer
go func() {
ch <- 0
println("out of routine")
}()
println("f1 start")
time.Sleep(time.Second * 3)
<-ch
println("End")
}
func f2() {
ch := make(chan int, 1) // size =1
go func() {
ch <- 0
println("out of routine")
}()
println("f1 start")
time.Sleep(time.Second * 3)
<-ch
println("End")
}
func main() {
//f1()
f2()
}
f1 最后不会输出End, 而f2则可以输出f2
创建了一个免费的Go知识星球社区,欢迎加入一起讨论吧
查看全部
无缓冲情况下,一把数据放入chan,如果没有其他协程取数据,接下来的操作是阻塞的
而在size=1的情况下, 第一个数据放入chan后,并不会马上阻塞,接下来的操作还是可以进行的。
看下面的代码 f1和f2的区别
package main
import "time"
func f1() {
ch := make(chan int) // no buffer
go func() {
ch <- 0
println("out of routine")
}()
println("f1 start")
time.Sleep(time.Second * 3)
<-ch
println("End")
}
func f2() {
ch := make(chan int, 1) // size =1
go func() {
ch <- 0
println("out of routine")
}()
println("f1 start")
time.Sleep(time.Second * 3)
<-ch
println("End")
}
func main() {
//f1()
f2()
}
f1 最后不会输出End, 而f2则可以输出f2
创建了一个免费的Go知识星球社区,欢迎加入一起讨论吧
go中的rand.Int() 为什么每次返回的都是同一个值,并不是随机?
Golang • 李魔佛 发表了文章 • 0 个评论 • 4637 次浏览 • 2021-10-21 17:38
package main
import "math/rand"
func GenRandom() chan int {
ch := make(chan int, 10)
go func() {
for {
ch <- rand.Int()
}
}()
return ch
}
func main() {
ch := GenRandom()
println(<-ch)
println("end of main")
}
返回的永远都是
5577006791947779410
原因是每次没有调用rand.Seed(xxxx), 导致随机种子都是 1 。 见官方文档Seed uses the provided seed value to initialize the default Source to a deterministic state. If Seed is not called, the generator behaves as if seeded by Seed(1).
所以如果想要每次随机值不一样
需要用时间戳作为随机种子
func GenRandom() chan int {
ch := make(chan int, 10)
go func() {
rand.Seed(time.Now().Unix())
for {
ch <- rand.Intn(200)
}
}()
return ch
} 查看全部
package main
import "math/rand"
func GenRandom() chan int {
ch := make(chan int, 10)
go func() {
for {
ch <- rand.Int()
}
}()
return ch
}
func main() {
ch := GenRandom()
println(<-ch)
println("end of main")
}
返回的永远都是
5577006791947779410
原因是每次没有调用rand.Seed(xxxx), 导致随机种子都是 1 。 见官方文档
Seed uses the provided seed value to initialize the default Source to a deterministic state. If Seed is not called, the generator behaves as if seeded by Seed(1).
所以如果想要每次随机值不一样
需要用时间戳作为随机种子
func GenRandom() chan int {
ch := make(chan int, 10)
go func() {
rand.Seed(time.Now().Unix())
for {
ch <- rand.Intn(200)
}
}()
return ch
}
go env 与go path,go module 的设置
Golang • 量化大师 发表了文章 • 0 个评论 • 4992 次浏览 • 2021-08-16 16:56
GOROOT指的Golang语言的安装路径,即Golang语言内置程序库所在的位置。通常在安装时环境变量会设置好GOROOT路径。当开发时,import标准库时并不需要额外安装,当程序运行后,也会去GOROOT路径下寻找相应程序。
二、GOPATH
GOPATH即存放第三方库的位置。通常开发时,会把GOPATH重新设置。
2.1 GOPATH目录
bin:放置编译后生成的可执行文件。
pkg:放置编译后生成的包/库的归档文件
src:放置项目和库的源文件;
2.1.1 src
用于以包(package)的形式组织并存放 Go 源文件,这里的包与 src 下的每个子目录是一一对应。例如,若一个源文件被声明属于 log 包,那么它就应当保存在 src/log 目录中。
并不是说 src 目录下不能存放 Go 源文件,一般在测试或演示的时候也可以把 Go 源文件直接放在 src目录下,但是这么做的话就只能声明该源文件属于 main 包了。正常开发中还是建议大家把 Go 源文件放入特定的目录中。
另外需要注意的是,Go语言会把通过go get命令获取到的库源文件下载到 src 目录下对应的文件夹当中。
2.1.2 pkg
用于存放通过go install命令安装某个包后的归档文件。归档文件是指那些名称以“.a”结尾的文件。
该目录与 GOROOT 目录(也就是Go语言的安装目录)下的 pkg 目录功能类似,区别在于这里的 pkg 目录专门用来存放项目代码的归档文件。
编译和安装项目代码的过程一般会以代码包为单位进行,比如 log 包被编译安装后,将生成一个名为 log.a 的归档文件,并存放在当前项目的 pkg 目录下。
2.1.3 bin
与 pkg 目录类似,在通过go install命令完成安装后,保存由 Go 命令源文件生成的可执行文件。在类 Unix 操作系统下,这个可执行文件的名称与命令源文件的文件名相同。
而在 Windows 操作系统下,这个可执行文件的名称则是命令源文件的文件名加 .exe 后缀。
2.2 设置和使用GOPATH
2.2.1 windows设置
在环境变量中添加GOPATH变量,将目录添加即可。
2.2.2 linux设置
设置当前目录为GOPATH:选择一个目录,在目录的命令行下执行
export GOPATH='pwd'
2.3 GOPATH缺点
只要第三方库不是官方程序库,都要放置到$GOPATH/src下才可以使用.
三 Go Modules
Golang从1.13版本开始有Go Modules.
3.1 使用Go Modules的好处
Go Modules可以将某个项目(文件夹)下的所有依赖整理成一个 go.mod 文件,里面写入了依赖的版本等 使用Go Modules之后我们可不用将代码放置在src下了
3.2 使用Go Modules
官方github关于Modules的WIKI:https://github.com/golang/go/wiki/Modules
使用 Go Modules 管理依赖后会在项目根目录下生成两个文件 go.mod 和 go.sum go.mod会记录当前项目的所有依赖项module test go 1.15 require http://github.com/gin-gonic/gin v1.6.3go.sum
会记录每个依赖库的版本和哈希值
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=3.3 如何开启Go Modules
要使用Go Modules首先要设置Go111Modules = on, GO111MODULE有三个值 on:开启 off:关闭 auto根据当前目录下是否有go.mod文件来判断是否使用modules功能
注意:**无论使用那种模式,module功能默认不在GOPATH目录下查找依赖文件,所以使用modules功能时请设置好代理
设置
GO111MODULE
# windows set GO111MODULE=on
# linux export GO111MODULE=on
然后使用go env查看
3.4 初始化Go Modules进入项目文件夹test
# 初始化路径 go mod init test
# 检测依赖 go mod tidy
# 如果有些依赖项未下载则需要下载 go mod download
# 导入依赖 go mod vendor3.5 GoLand开启Go Modules
文件(File) 设置(Setting) 在GO选项下选择GO MODULES 启用Go Modules 设置代理服务器
3.6 更新依赖# 检测依赖 go mod tidy # 如果有些依赖项未下载则需要下载 go mod download # 导入依赖 go mod vendor3.7 Git使用GO MODULES注意事项
在git中需要把vendor文件夹放入白名单中,不然项目体积会很大。 git设置白名单方式为在git托管的项目根目录新建 .gitignore 文件,设置忽略即可,但是 go.mod 和 go.sum 不要忽略。
另一人clone项目后在本地进行依赖更新(同上方依赖更新)即可
3.8 Go Module常用命令go mod init
# 初始化go.mod go mod tidy
# 更新依赖文件 go mod download
# 下载依赖文件 go mod vendor
# 将依赖转移至本地的vendor文件 go mod edit
# 手动修改依赖文件 go mod graph
# 打印依赖图 go mod verify
# 校验依赖 go mod why
# 解释为什么需要依赖四、GO PROXY
GOPROXY 是Go语言官方提供的一种通过中间代理商来为用户提供包下载服务的方式。要使用 GOPROXY 只需要设置环境变量 GOPROXY 即可。
4.1 国内镜像
// 阿里云镜像
GOPROXY=https://mirrors.aliyun.com/goproxy/ // 中国golang镜像
GOPROXY=https://goproxy.io
// 七牛云为中国的gopher提供了一个免费合法的代理goproxy.cn,其已经开源。只需一条简单命令就可以使用该代理:go env -w GOPROXY=https://goproxy.cn,direct五、Go Get
执行go get命令,在下载依赖包的同时还可以指定依赖包的版本。
运行go get -u命令会将项目中的包升级到最新的次要版本或者修订版本;
运行go get -u=patch命令会将项目中的包升级到最新的修订版本;
运行go get [包名]@[版本号]命令会下载对应包的指定版本或者将对应包升级到指定的版本。
提示:go get [包名]@[版本号]命令中版本号可以是 x.y.z 的形式,
例如 go get foo@v1.2.3,也可以是 git 上的分支或 tag,例如 go get foo@master,还可以是 git 提交时的哈希值,例如 go get foo@e3702bed2。
六、godep
godep 是一个Go语言官方提供的通过 vender 模式来管理第三方依赖的工具,类似的还有由社区维护的准官方包管理工具 dep。
Go语言从 1.5 版本开始开始引入 vendor 模式,如果项目目录下有 vendor 目录,那么Go语言编译器会优先使用 vendor 内的包进行编译、测试等。
6.1 安装godepgo get github.com/tools/godep命令执行成功后会将 godep 工具的源码下载到 GOPATH 的 src 录下对应的文件夹中,同时还会在 GOPATH 的 bin 目录下生成一个名为 godep.exe 的可执行文件。
6.2 配置环境变量
6.3 godep基本命令
命令 说明godep save 将依赖包的信息保存到Godeps.json文件中 godep go 使用保存的依赖项运行go工具 godep get 下载并安装指定的包 godep path 打印依赖的GOPATH路径 godep restore 在GOPATH中拉取依赖的版本 godep update 更新选定的包或go版本 godep diff 显示当前和以前保存的依赖项集之间的差异 godep version 查看版本信息6.4 使用godep
执行godep save命令,会在当前目录中创建 Godeps 和 vender 两个文件夹。
Godeps 文件夹下会生成一个 Godeps.json 文件,用来记录项目中所依赖的包信息;vender 目录则是用来保存当前项目所依赖的所有第三方包。生成的 Godeps.json 文件的结构如下所示:{
"ImportPath": "main",//项目路径信息
"GoVersion": "go1.13",//go语言版本号
"GodepVersion": "v80",//godep版本号
"Deps": [//当前引用的包
{
"ImportPath": "github.com/go-gomail/gomail",//依赖包路径
"Comment": "2.0.0-23-g81ebce5",//版本号
"Rev": "81ebce5c23dfd25c6c67194b37d3dd3f338c98b1"//哈希值
}
]
}
当所引用的第三方包要升级只需要修改Godep.json里面的依赖包的版本号,让后执行godep save命令即可。
godep查找依赖顺序: 在项目路径下的vender文件夹中查找 到GOPATH/src目录查找 查看全部
GOROOT指的Golang语言的安装路径,即Golang语言内置程序库所在的位置。通常在安装时环境变量会设置好GOROOT路径。当开发时,import标准库时并不需要额外安装,当程序运行后,也会去GOROOT路径下寻找相应程序。
二、GOPATH
GOPATH即存放第三方库的位置。通常开发时,会把GOPATH重新设置。
2.1 GOPATH目录
bin:放置编译后生成的可执行文件。
pkg:放置编译后生成的包/库的归档文件
src:放置项目和库的源文件;
2.1.1 src
用于以包(package)的形式组织并存放 Go 源文件,这里的包与 src 下的每个子目录是一一对应。例如,若一个源文件被声明属于 log 包,那么它就应当保存在 src/log 目录中。
并不是说 src 目录下不能存放 Go 源文件,一般在测试或演示的时候也可以把 Go 源文件直接放在 src目录下,但是这么做的话就只能声明该源文件属于 main 包了。正常开发中还是建议大家把 Go 源文件放入特定的目录中。
另外需要注意的是,Go语言会把通过go get命令获取到的库源文件下载到 src 目录下对应的文件夹当中。
2.1.2 pkg
用于存放通过go install命令安装某个包后的归档文件。归档文件是指那些名称以“.a”结尾的文件。
该目录与 GOROOT 目录(也就是Go语言的安装目录)下的 pkg 目录功能类似,区别在于这里的 pkg 目录专门用来存放项目代码的归档文件。
编译和安装项目代码的过程一般会以代码包为单位进行,比如 log 包被编译安装后,将生成一个名为 log.a 的归档文件,并存放在当前项目的 pkg 目录下。
2.1.3 bin
与 pkg 目录类似,在通过go install命令完成安装后,保存由 Go 命令源文件生成的可执行文件。在类 Unix 操作系统下,这个可执行文件的名称与命令源文件的文件名相同。
而在 Windows 操作系统下,这个可执行文件的名称则是命令源文件的文件名加 .exe 后缀。
2.2 设置和使用GOPATH
2.2.1 windows设置
在环境变量中添加GOPATH变量,将目录添加即可。
2.2.2 linux设置
设置当前目录为GOPATH:选择一个目录,在目录的命令行下执行
export GOPATH='pwd'
2.3 GOPATH缺点
只要第三方库不是官方程序库,都要放置到$GOPATH/src下才可以使用.
三 Go Modules
Golang从1.13版本开始有Go Modules.
3.1 使用Go Modules的好处
Go Modules可以将某个项目(文件夹)下的所有依赖整理成一个 go.mod 文件,里面写入了依赖的版本等 使用Go Modules之后我们可不用将代码放置在src下了
3.2 使用Go Modules
官方github关于Modules的WIKI:https://github.com/golang/go/wiki/Modules
使用 Go Modules 管理依赖后会在项目根目录下生成两个文件 go.mod 和 go.sum go.mod会记录当前项目的所有依赖项module test go 1.15 require http://github.com/gin-gonic/gin v1.6.3go.sum
会记录每个依赖库的版本和哈希值
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=3.3 如何开启Go Modules
要使用Go Modules首先要设置Go111Modules = on, GO111MODULE有三个值 on:开启 off:关闭 auto根据当前目录下是否有go.mod文件来判断是否使用modules功能
注意:**无论使用那种模式,module功能默认不在GOPATH目录下查找依赖文件,所以使用modules功能时请设置好代理
设置
GO111MODULE
# windows set GO111MODULE=on
# linux export GO111MODULE=on
然后使用go env查看
3.4 初始化Go Modules进入项目文件夹test
# 初始化路径 go mod init test
# 检测依赖 go mod tidy
# 如果有些依赖项未下载则需要下载 go mod download
# 导入依赖 go mod vendor3.5 GoLand开启Go Modules
文件(File) 设置(Setting) 在GO选项下选择GO MODULES 启用Go Modules 设置代理服务器
3.6 更新依赖# 检测依赖 go mod tidy # 如果有些依赖项未下载则需要下载 go mod download # 导入依赖 go mod vendor3.7 Git使用GO MODULES注意事项
在git中需要把vendor文件夹放入白名单中,不然项目体积会很大。 git设置白名单方式为在git托管的项目根目录新建 .gitignore 文件,设置忽略即可,但是 go.mod 和 go.sum 不要忽略。
另一人clone项目后在本地进行依赖更新(同上方依赖更新)即可
3.8 Go Module常用命令go mod init
# 初始化go.mod go mod tidy
# 更新依赖文件 go mod download
# 下载依赖文件 go mod vendor
# 将依赖转移至本地的vendor文件 go mod edit
# 手动修改依赖文件 go mod graph
# 打印依赖图 go mod verify
# 校验依赖 go mod why
# 解释为什么需要依赖四、GO PROXY
GOPROXY 是Go语言官方提供的一种通过中间代理商来为用户提供包下载服务的方式。要使用 GOPROXY 只需要设置环境变量 GOPROXY 即可。
4.1 国内镜像
// 阿里云镜像
GOPROXY=https://mirrors.aliyun.com/goproxy/ // 中国golang镜像
GOPROXY=https://goproxy.io
// 七牛云为中国的gopher提供了一个免费合法的代理goproxy.cn,其已经开源。只需一条简单命令就可以使用该代理:go env -w GOPROXY=https://goproxy.cn,direct五、Go Get
执行go get命令,在下载依赖包的同时还可以指定依赖包的版本。
运行go get -u命令会将项目中的包升级到最新的次要版本或者修订版本;
运行go get -u=patch命令会将项目中的包升级到最新的修订版本;
运行go get [包名]@[版本号]命令会下载对应包的指定版本或者将对应包升级到指定的版本。
提示:go get [包名]@[版本号]命令中版本号可以是 x.y.z 的形式,
例如 go get foo@v1.2.3,也可以是 git 上的分支或 tag,例如 go get foo@master,还可以是 git 提交时的哈希值,例如 go get foo@e3702bed2。
六、godep
godep 是一个Go语言官方提供的通过 vender 模式来管理第三方依赖的工具,类似的还有由社区维护的准官方包管理工具 dep。
Go语言从 1.5 版本开始开始引入 vendor 模式,如果项目目录下有 vendor 目录,那么Go语言编译器会优先使用 vendor 内的包进行编译、测试等。
6.1 安装godepgo get github.com/tools/godep命令执行成功后会将 godep 工具的源码下载到 GOPATH 的 src 录下对应的文件夹中,同时还会在 GOPATH 的 bin 目录下生成一个名为 godep.exe 的可执行文件。
6.2 配置环境变量
6.3 godep基本命令
命令 说明godep save 将依赖包的信息保存到Godeps.json文件中 godep go 使用保存的依赖项运行go工具 godep get 下载并安装指定的包 godep path 打印依赖的GOPATH路径 godep restore 在GOPATH中拉取依赖的版本 godep update 更新选定的包或go版本 godep diff 显示当前和以前保存的依赖项集之间的差异 godep version 查看版本信息6.4 使用godep
执行godep save命令,会在当前目录中创建 Godeps 和 vender 两个文件夹。
Godeps 文件夹下会生成一个 Godeps.json 文件,用来记录项目中所依赖的包信息;vender 目录则是用来保存当前项目所依赖的所有第三方包。生成的 Godeps.json 文件的结构如下所示:
{
"ImportPath": "main",//项目路径信息
"GoVersion": "go1.13",//go语言版本号
"GodepVersion": "v80",//godep版本号
"Deps": [//当前引用的包
{
"ImportPath": "github.com/go-gomail/gomail",//依赖包路径
"Comment": "2.0.0-23-g81ebce5",//版本号
"Rev": "81ebce5c23dfd25c6c67194b37d3dd3f338c98b1"//哈希值
}
]
}
当所引用的第三方包要升级只需要修改Godep.json里面的依赖包的版本号,让后执行godep save命令即可。
godep查找依赖顺序: 在项目路径下的vender文件夹中查找 到GOPATH/src目录查找
Go的包管理比python烂得多,不知道为啥还要被吹捧
python • 李魔佛 发表了文章 • 0 个评论 • 2072 次浏览 • 2021-08-07 23:53
GO111MODULE与GOPATH不兼容
2. 竟然要搞动系统的环境变量。
主要本人使用vim开发,编译运行都在shell底下,windows也是在cmd下跑的
3. 下载包的地址被墙,需要设置国内的地址。并且官方的包镜像也在github,其下载速度,你懂的。
蜗牛一样的。 查看全部
GO111MODULE与GOPATH不兼容
2. 竟然要搞动系统的环境变量。
主要本人使用vim开发,编译运行都在shell底下,windows也是在cmd下跑的
3. 下载包的地址被墙,需要设置国内的地址。并且官方的包镜像也在github,其下载速度,你懂的。
蜗牛一样的。
30天掌握Golang 教程系列 第一课 基础知识
量化交易-Ptrade-QMT • 量化大师 发表了文章 • 0 个评论 • 2219 次浏览 • 2021-08-04 01:15
这里有一个Golang的练习库,输入基础入门的资料。 大家可以先练习练习:
https://github.com/Rockyzsu/GolangLearning/tree/master/Go-Notes
基础语法是没办法绕过的,如果前期不打扎实,后期也会不断来回折腾。除非你做的项目只是一次性的,否则,磨刀不误砍柴工,还是打扎实。 把上面的github的例子弄懂,这个Go-notes的好处是,如果遇到你不懂的,可以马上查找相关的资料。如果全部都懂的话,可以进阶到第二阶段。
个人觉得还是得要多看看别人的代码,看多了,其实你写代码也会有灵感。(虽然有些人写的代码很烂,但是也可以自己做过标号,避免自己以后写出同样的代码。)
PS: 本来我想从0开始写教程,不过网上其实也有很多教程,很多视频。 也有不少的书籍可以学。所以就没有必要重复造轮子了。
而实际的情况是,入门的人数需求是100个人,而进阶的需求是只有60个人,而深入理解并需要对应的教程的,可能只有20人不到。
所以想着写golang教程,最受欢迎的其实是hello world教程。
实际写起来也很容易,无法就是if - else,for, 切片,数组,通道,goroutine,结构体等。
不过对于笔者的能力提升是没有一点点用处的,当日提升知名度除外。
所以入门系列的基础课,我这里就一比带过。可以留一些比较容易踩到的坑。
当然这个基础知识不可能 第一天就全部搞定。 可以多花几天甚至一周的时间。
查看全部
这里有一个Golang的练习库,输入基础入门的资料。 大家可以先练习练习:
https://github.com/Rockyzsu/GolangLearning/tree/master/Go-Notes
基础语法是没办法绕过的,如果前期不打扎实,后期也会不断来回折腾。除非你做的项目只是一次性的,否则,磨刀不误砍柴工,还是打扎实。 把上面的github的例子弄懂,这个Go-notes的好处是,如果遇到你不懂的,可以马上查找相关的资料。如果全部都懂的话,可以进阶到第二阶段。
个人觉得还是得要多看看别人的代码,看多了,其实你写代码也会有灵感。(虽然有些人写的代码很烂,但是也可以自己做过标号,避免自己以后写出同样的代码。)
PS: 本来我想从0开始写教程,不过网上其实也有很多教程,很多视频。 也有不少的书籍可以学。所以就没有必要重复造轮子了。
而实际的情况是,入门的人数需求是100个人,而进阶的需求是只有60个人,而深入理解并需要对应的教程的,可能只有20人不到。
所以想着写golang教程,最受欢迎的其实是hello world教程。
实际写起来也很容易,无法就是if - else,for, 切片,数组,通道,goroutine,结构体等。
不过对于笔者的能力提升是没有一点点用处的,当日提升知名度除外。
所以入门系列的基础课,我这里就一比带过。可以留一些比较容易踩到的坑。
当然这个基础知识不可能 第一天就全部搞定。 可以多花几天甚至一周的时间。
vim定义快捷键 运行go程序
Linux • 李魔佛 发表了文章 • 0 个评论 • 2150 次浏览 • 2021-07-23 16:27
nnoremap gr :!go run %<CR>
所以你可以很容易地输入gr你的vim,它就会执行。
nnoremap gr :!go run %<CR>
所以你可以很容易地输入gr你的vim,它就会执行。
github.com/lestrrat-go/libxml2 这个xpath包在windows下无法使用
Golang • 马化云 发表了文章 • 0 个评论 • 1070 次浏览 • 2023-08-18 12:11
(base) PS C:\git\qiniu_web_gin> go run .\main.go
# github.com/lestrrat-go/libxml2/xpath
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:40:35: undefined: clib.XMLXPathObjectType
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:45:14: undefined: clib.XMLXPathObjectFloat64
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:50:14: undefined: clib.XMLXPathObjectBool
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:74:18: undefined: clib.XMLXPathObjectNodeList
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:91:18: undefined: clib.XMLXPathObjectNodeList
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:124:7: undefined: clib.XMLXPathFreeObject
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:129:19: undefined: clib.XMLXPathCompile
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:149:7: undefined: clib.XMLXPathFreeCompExpr
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:163:22: undefined: clib.XMLXPathNewContext
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:179:14: undefined: clib.XMLXPathContextSetContextNode
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:179:14: too many errors
(base) PS C:\git\qiniu_web_gin> go get github.com/lestrrat-go/libxml2
(base) PS C:\git\qiniu_web_gin>
然后到作者的官网上逛了一圈,出现这个问题,需要自己编译一个libxml2 windows版本的
官方给出的是源码:
libxml2-2.11.5-win-build Latest
Corresponding to official release version 2.11.5.
然后编译C的源码,需要很多的工具链和依赖。
windows至少需要Visual Studio, 不是vs code呢。 Visual Studio安装完,至少要被占用10GB的空间。
libxml2 + iconv + msvc 在windows下生成使用库
为了跨平台的解析xml,偶然获得Linux下比较好用的一个xml的解析库libxml2,使用起来确实比较简单,方便;但移植到windows下后发下使用上存在问题:
无法解析格式位GB2312类型的XML文件,但由于一些外部因素,Windows下必须使用GB2312格式
在网上查看了诸多教程,有很多编译生成libxml2库的文章,但都不支持iconv,仔细阅读README后,终于生成了可用的libxml2.lib库,记录下来备用
操作系统:windows 7 x64
版本:libiconv-1.15, libxml2 Github版本
Visual Studio版本:vs2015
Cygwin:x64
以下操作皆为生成x64位库,32位的基本类似,可以查看具体的README。
所以想想还是算了,直接切换到ubuntu开发了。惹不起,还躲不起吗 :(
我:@lestrrat Hi, is that mean it can't work on windows if i dont build it with visual studio or cgywin like?
作者:It's the same as when you are building a C program. You build in the same arch/os as the where you intend to run the program.
我:Thanks a lot. Instsall vs environment taks lots of time, so i switch to the ubuntu to "quick fix this issue" :(
逃-》
查看全部
(base) PS C:\git\qiniu_web_gin> go run .\main.go
# github.com/lestrrat-go/libxml2/xpath
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:40:35: undefined: clib.XMLXPathObjectType
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:45:14: undefined: clib.XMLXPathObjectFloat64
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:50:14: undefined: clib.XMLXPathObjectBool
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:74:18: undefined: clib.XMLXPathObjectNodeList
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:91:18: undefined: clib.XMLXPathObjectNodeList
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:124:7: undefined: clib.XMLXPathFreeObject
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:129:19: undefined: clib.XMLXPathCompile
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:149:7: undefined: clib.XMLXPathFreeCompExpr
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:163:22: undefined: clib.XMLXPathNewContext
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:179:14: undefined: clib.XMLXPathContextSetContextNode
C:\Users\xda\go\pkg\mod\github.com\lestrrat-go\libxml2@v0.0.0-20201123224832-e6d9de61b80d\xpath\xpath.go:179:14: too many errors
(base) PS C:\git\qiniu_web_gin> go get github.com/lestrrat-go/libxml2
(base) PS C:\git\qiniu_web_gin>
然后到作者的官网上逛了一圈,出现这个问题,需要自己编译一个libxml2 windows版本的
官方给出的是源码:
libxml2-2.11.5-win-build Latest
Corresponding to official release version 2.11.5.
然后编译C的源码,需要很多的工具链和依赖。
windows至少需要Visual Studio, 不是vs code呢。 Visual Studio安装完,至少要被占用10GB的空间。
libxml2 + iconv + msvc 在windows下生成使用库
为了跨平台的解析xml,偶然获得Linux下比较好用的一个xml的解析库libxml2,使用起来确实比较简单,方便;但移植到windows下后发下使用上存在问题:
无法解析格式位GB2312类型的XML文件,但由于一些外部因素,Windows下必须使用GB2312格式
在网上查看了诸多教程,有很多编译生成libxml2库的文章,但都不支持iconv,仔细阅读README后,终于生成了可用的libxml2.lib库,记录下来备用
操作系统:windows 7 x64
版本:libiconv-1.15, libxml2 Github版本
Visual Studio版本:vs2015
Cygwin:x64
以下操作皆为生成x64位库,32位的基本类似,可以查看具体的README。
所以想想还是算了,直接切换到ubuntu开发了。惹不起,还躲不起吗 :(
我:@lestrrat Hi, is that mean it can't work on windows if i dont build it with visual studio or cgywin like?
作者:It's the same as when you are building a C program. You build in the same arch/os as the where you intend to run the program.
我:Thanks a lot. Instsall vs environment taks lots of time, so i switch to the ubuntu to "quick fix this issue" :(
逃-》
golang执行系统shell命令,并获取返回内容
Golang • 马化云 发表了文章 • 0 个评论 • 1617 次浏览 • 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(*) 的写法
Golang • 马化云 发表了文章 • 0 个评论 • 1566 次浏览 • 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操作 保存这篇文章就足够了)
Golang • 马化云 发表了文章 • 0 个评论 • 1644 次浏览 • 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 集合,并判断元素是否存在
Golang • 李魔佛 发表了文章 • 0 个评论 • 1728 次浏览 • 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
Golang • 李魔佛 发表了文章 • 0 个评论 • 1652 次浏览 • 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 前端与后端的正确写法
Golang • 李魔佛 发表了文章 • 0 个评论 • 2510 次浏览 • 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应用 无法下载第三方包 解决办法
Golang • 李魔佛 发表了文章 • 0 个评论 • 2048 次浏览 • 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
ubuntu(centos)下golang下载libxml2 报错信息, go 安装libxml2
Golang • 李魔佛 发表了文章 • 0 个评论 • 1960 次浏览 • 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,否则弄得系统一堆依赖问题。
REST ful API的规范 delete方法不建议在body放入数据
网络 • 李魔佛 发表了文章 • 0 个评论 • 2260 次浏览 • 2021-12-27 14:58
因为资源的唯一性,所以就没必要再在body里面放入其他的数据了.
什么? 通过uri不能确定资源的唯一? 那么你这个设计就不是REST规范了.
那PUT这些操作也无法准确更新资源了.
因为资源的唯一性,所以就没必要再在body里面放入其他的数据了.
什么? 通过uri不能确定资源的唯一? 那么你这个设计就不是REST规范了.
那PUT这些操作也无法准确更新资源了.
golang的时间格式化 做法有点像格力手机的开机画面是董小姐
闲聊 • 李魔佛 发表了文章 • 0 个评论 • 1687 次浏览 • 2021-12-20 13:01
过去用java,python,php,等语言,将一个时间格式化成一个字符串都是用“yyy-MM-dd hh:mm:ss”之类的方法,golang 的格式化方法真令我大开眼界
先看官方文档说明:
func (Time) Format
func (t Time) Format(layout string) string
Format returns a textual representation of the time value formatted according to layout, which defines the format by showing how the reference time, defined to be
Mon Jan 2 15:04:05 -0700 MST 2006
would be displayed if it were the value; it serves as an example of the desired output. The same display rules will then be applied to the time value. Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard and convenient representations of the reference time. For more information about the formats and the definition of the reference time, see the documentation for ANSIC and the other constants defined by this package.
下面给个代码:
fmt.Println(time.Now().Format("2006-01-02 150405"))
要注意那时间,只能是2006-01-02 15:04:05分,其它的时间都不行,真是够绝。
做法有点像格力手机的开机画面是董小姐。
用个语言还得记住你golang的生日?? 查看全部
过去用java,python,php,等语言,将一个时间格式化成一个字符串都是用“yyy-MM-dd hh:mm:ss”之类的方法,golang 的格式化方法真令我大开眼界
先看官方文档说明:
func (Time) Format
func (t Time) Format(layout string) string
Format returns a textual representation of the time value formatted according to layout, which defines the format by showing how the reference time, defined to be
Mon Jan 2 15:04:05 -0700 MST 2006
would be displayed if it were the value; it serves as an example of the desired output. The same display rules will then be applied to the time value. Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard and convenient representations of the reference time. For more information about the formats and the definition of the reference time, see the documentation for ANSIC and the other constants defined by this package.
下面给个代码:
fmt.Println(time.Now().Format("2006-01-02 150405"))
要注意那时间,只能是2006-01-02 15:04:05分,其它的时间都不行,真是够绝。
做法有点像格力手机的开机画面是董小姐。
用个语言还得记住你golang的生日??
30天学会Golang
Golang • 马化云 发表了文章 • 0 个评论 • 1850 次浏览 • 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 ?
Golang • 李魔佛 发表了文章 • 0 个评论 • 2145 次浏览 • 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
Golang • 李魔佛 发表了文章 • 0 个评论 • 2939 次浏览 • 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
Golang • 李魔佛 发表了文章 • 0 个评论 • 1806 次浏览 • 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文件操作之 移动文件
Golang • 李魔佛 发表了文章 • 0 个评论 • 4874 次浏览 • 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
golang:为什么chan关闭了也无法接受到内容呢?
Golang • 李魔佛 发表了文章 • 0 个评论 • 1914 次浏览 • 2021-11-18 20:12
import "fmt"
func main() {
ch := make(chan int)
ch <- 1
close(ch)
n, ok := <-ch
if !ok {
fmt.Println("Error")
}
fmt.Println(n)
var input string
fmt.Scanln(&input)
}
实际程序死锁。
有人问,chan close后不会可以被读取到了吗?
但是实际程序运行到:
ch <- 1
这里, 已经被阻塞,导致报错,无法接下来的close操作。
加入打印信息:package main
import "fmt"
func main() {
ch := make(chan int)
fmt.Println("start")
ch <- 1
fmt.Println("next")
close(ch)
n, ok := <-ch
if !ok {
fmt.Println("Error")
}
fmt.Println(n)
var input string
fmt.Scanln(&input)
}
实际只打印到start, next那个已经不输出了。:!go run channel_close.go
start
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/home/admin/git/GolangLearning/helloworld/channel/channel_close.go:8 +0xa8
exit status 2
shell returned 1
正确的修改:package main
import "fmt"
func main() {
ch := make(chan int)
go func() {
fmt.Println("start")
ch <- 1
fmt.Println("next")
close(ch)
}()
n, ok := <-ch
if !ok {
fmt.Println("Error")
}
fmt.Println(n)
var input string
fmt.Scanln(&input)
}
创建了一个免费的Go知识星球社区,欢迎加入一起讨论吧
查看全部
package main
import "fmt"
func main() {
ch := make(chan int)
ch <- 1
close(ch)
n, ok := <-ch
if !ok {
fmt.Println("Error")
}
fmt.Println(n)
var input string
fmt.Scanln(&input)
}
实际程序死锁。
有人问,chan close后不会可以被读取到了吗?
但是实际程序运行到:
ch <- 1
这里, 已经被阻塞,导致报错,无法接下来的close操作。
加入打印信息:
package main
import "fmt"
func main() {
ch := make(chan int)
fmt.Println("start")
ch <- 1
fmt.Println("next")
close(ch)
n, ok := <-ch
if !ok {
fmt.Println("Error")
}
fmt.Println(n)
var input string
fmt.Scanln(&input)
}
实际只打印到start, next那个已经不输出了。
:!go run channel_close.go
start
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/home/admin/git/GolangLearning/helloworld/channel/channel_close.go:8 +0xa8
exit status 2
shell returned 1
正确的修改:
package main
import "fmt"
func main() {
ch := make(chan int)
go func() {
fmt.Println("start")
ch <- 1
fmt.Println("next")
close(ch)
}()
n, ok := <-ch
if !ok {
fmt.Println("Error")
}
fmt.Println(n)
var input string
fmt.Scanln(&input)
}
创建了一个免费的Go知识星球社区,欢迎加入一起讨论吧
go get 加 -u 和不加 -u 参数的区别
Golang • 李魔佛 发表了文章 • 0 个评论 • 1769 次浏览 • 2021-11-09 14:44
如果不加这个 -u 标记,执行 go get 一个已有的代码包,会发现命令什么都不执行。
只有加了 -u 标记,命令会去执行 git pull 命令拉取最新的代码包的最新版本,下载并安装。 查看全部
如果已经下载过一个代码包,但是这个代码包又有更新了,那么这时候可以直接用 -u 标记来更新本地的对应的代码包。
如果不加这个 -u 标记,执行 go get 一个已有的代码包,会发现命令什么都不执行。
只有加了 -u 标记,命令会去执行 git pull 命令拉取最新的代码包的最新版本,下载并安装。
golang中chan 无缓冲和 chan有缓冲 长度size设为1的区别
Golang • 低调的哥哥 发表了文章 • 0 个评论 • 3278 次浏览 • 2021-10-28 09:15
无缓冲情况下,一把数据放入chan,如果没有其他协程取数据,接下来的操作是阻塞的
而在size=1的情况下, 第一个数据放入chan后,并不会马上阻塞,接下来的操作还是可以进行的。
看下面的代码 f1和f2的区别
package main
import "time"
func f1() {
ch := make(chan int) // no buffer
go func() {
ch <- 0
println("out of routine")
}()
println("f1 start")
time.Sleep(time.Second * 3)
<-ch
println("End")
}
func f2() {
ch := make(chan int, 1) // size =1
go func() {
ch <- 0
println("out of routine")
}()
println("f1 start")
time.Sleep(time.Second * 3)
<-ch
println("End")
}
func main() {
//f1()
f2()
}
f1 最后不会输出End, 而f2则可以输出f2
创建了一个免费的Go知识星球社区,欢迎加入一起讨论吧
查看全部
无缓冲情况下,一把数据放入chan,如果没有其他协程取数据,接下来的操作是阻塞的
而在size=1的情况下, 第一个数据放入chan后,并不会马上阻塞,接下来的操作还是可以进行的。
看下面的代码 f1和f2的区别
package main
import "time"
func f1() {
ch := make(chan int) // no buffer
go func() {
ch <- 0
println("out of routine")
}()
println("f1 start")
time.Sleep(time.Second * 3)
<-ch
println("End")
}
func f2() {
ch := make(chan int, 1) // size =1
go func() {
ch <- 0
println("out of routine")
}()
println("f1 start")
time.Sleep(time.Second * 3)
<-ch
println("End")
}
func main() {
//f1()
f2()
}
f1 最后不会输出End, 而f2则可以输出f2
创建了一个免费的Go知识星球社区,欢迎加入一起讨论吧
go中的rand.Int() 为什么每次返回的都是同一个值,并不是随机?
Golang • 李魔佛 发表了文章 • 0 个评论 • 4637 次浏览 • 2021-10-21 17:38
package main
import "math/rand"
func GenRandom() chan int {
ch := make(chan int, 10)
go func() {
for {
ch <- rand.Int()
}
}()
return ch
}
func main() {
ch := GenRandom()
println(<-ch)
println("end of main")
}
返回的永远都是
5577006791947779410
原因是每次没有调用rand.Seed(xxxx), 导致随机种子都是 1 。 见官方文档Seed uses the provided seed value to initialize the default Source to a deterministic state. If Seed is not called, the generator behaves as if seeded by Seed(1).
所以如果想要每次随机值不一样
需要用时间戳作为随机种子
func GenRandom() chan int {
ch := make(chan int, 10)
go func() {
rand.Seed(time.Now().Unix())
for {
ch <- rand.Intn(200)
}
}()
return ch
} 查看全部
package main
import "math/rand"
func GenRandom() chan int {
ch := make(chan int, 10)
go func() {
for {
ch <- rand.Int()
}
}()
return ch
}
func main() {
ch := GenRandom()
println(<-ch)
println("end of main")
}
返回的永远都是
5577006791947779410
原因是每次没有调用rand.Seed(xxxx), 导致随机种子都是 1 。 见官方文档
Seed uses the provided seed value to initialize the default Source to a deterministic state. If Seed is not called, the generator behaves as if seeded by Seed(1).
所以如果想要每次随机值不一样
需要用时间戳作为随机种子
func GenRandom() chan int {
ch := make(chan int, 10)
go func() {
rand.Seed(time.Now().Unix())
for {
ch <- rand.Intn(200)
}
}()
return ch
}
go env 与go path,go module 的设置
Golang • 量化大师 发表了文章 • 0 个评论 • 4992 次浏览 • 2021-08-16 16:56
GOROOT指的Golang语言的安装路径,即Golang语言内置程序库所在的位置。通常在安装时环境变量会设置好GOROOT路径。当开发时,import标准库时并不需要额外安装,当程序运行后,也会去GOROOT路径下寻找相应程序。
二、GOPATH
GOPATH即存放第三方库的位置。通常开发时,会把GOPATH重新设置。
2.1 GOPATH目录
bin:放置编译后生成的可执行文件。
pkg:放置编译后生成的包/库的归档文件
src:放置项目和库的源文件;
2.1.1 src
用于以包(package)的形式组织并存放 Go 源文件,这里的包与 src 下的每个子目录是一一对应。例如,若一个源文件被声明属于 log 包,那么它就应当保存在 src/log 目录中。
并不是说 src 目录下不能存放 Go 源文件,一般在测试或演示的时候也可以把 Go 源文件直接放在 src目录下,但是这么做的话就只能声明该源文件属于 main 包了。正常开发中还是建议大家把 Go 源文件放入特定的目录中。
另外需要注意的是,Go语言会把通过go get命令获取到的库源文件下载到 src 目录下对应的文件夹当中。
2.1.2 pkg
用于存放通过go install命令安装某个包后的归档文件。归档文件是指那些名称以“.a”结尾的文件。
该目录与 GOROOT 目录(也就是Go语言的安装目录)下的 pkg 目录功能类似,区别在于这里的 pkg 目录专门用来存放项目代码的归档文件。
编译和安装项目代码的过程一般会以代码包为单位进行,比如 log 包被编译安装后,将生成一个名为 log.a 的归档文件,并存放在当前项目的 pkg 目录下。
2.1.3 bin
与 pkg 目录类似,在通过go install命令完成安装后,保存由 Go 命令源文件生成的可执行文件。在类 Unix 操作系统下,这个可执行文件的名称与命令源文件的文件名相同。
而在 Windows 操作系统下,这个可执行文件的名称则是命令源文件的文件名加 .exe 后缀。
2.2 设置和使用GOPATH
2.2.1 windows设置
在环境变量中添加GOPATH变量,将目录添加即可。
2.2.2 linux设置
设置当前目录为GOPATH:选择一个目录,在目录的命令行下执行
export GOPATH='pwd'
2.3 GOPATH缺点
只要第三方库不是官方程序库,都要放置到$GOPATH/src下才可以使用.
三 Go Modules
Golang从1.13版本开始有Go Modules.
3.1 使用Go Modules的好处
Go Modules可以将某个项目(文件夹)下的所有依赖整理成一个 go.mod 文件,里面写入了依赖的版本等 使用Go Modules之后我们可不用将代码放置在src下了
3.2 使用Go Modules
官方github关于Modules的WIKI:https://github.com/golang/go/wiki/Modules
使用 Go Modules 管理依赖后会在项目根目录下生成两个文件 go.mod 和 go.sum go.mod会记录当前项目的所有依赖项module test go 1.15 require http://github.com/gin-gonic/gin v1.6.3go.sum
会记录每个依赖库的版本和哈希值
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=3.3 如何开启Go Modules
要使用Go Modules首先要设置Go111Modules = on, GO111MODULE有三个值 on:开启 off:关闭 auto根据当前目录下是否有go.mod文件来判断是否使用modules功能
注意:**无论使用那种模式,module功能默认不在GOPATH目录下查找依赖文件,所以使用modules功能时请设置好代理
设置
GO111MODULE
# windows set GO111MODULE=on
# linux export GO111MODULE=on
然后使用go env查看
3.4 初始化Go Modules进入项目文件夹test
# 初始化路径 go mod init test
# 检测依赖 go mod tidy
# 如果有些依赖项未下载则需要下载 go mod download
# 导入依赖 go mod vendor3.5 GoLand开启Go Modules
文件(File) 设置(Setting) 在GO选项下选择GO MODULES 启用Go Modules 设置代理服务器
3.6 更新依赖# 检测依赖 go mod tidy # 如果有些依赖项未下载则需要下载 go mod download # 导入依赖 go mod vendor3.7 Git使用GO MODULES注意事项
在git中需要把vendor文件夹放入白名单中,不然项目体积会很大。 git设置白名单方式为在git托管的项目根目录新建 .gitignore 文件,设置忽略即可,但是 go.mod 和 go.sum 不要忽略。
另一人clone项目后在本地进行依赖更新(同上方依赖更新)即可
3.8 Go Module常用命令go mod init
# 初始化go.mod go mod tidy
# 更新依赖文件 go mod download
# 下载依赖文件 go mod vendor
# 将依赖转移至本地的vendor文件 go mod edit
# 手动修改依赖文件 go mod graph
# 打印依赖图 go mod verify
# 校验依赖 go mod why
# 解释为什么需要依赖四、GO PROXY
GOPROXY 是Go语言官方提供的一种通过中间代理商来为用户提供包下载服务的方式。要使用 GOPROXY 只需要设置环境变量 GOPROXY 即可。
4.1 国内镜像
// 阿里云镜像
GOPROXY=https://mirrors.aliyun.com/goproxy/ // 中国golang镜像
GOPROXY=https://goproxy.io
// 七牛云为中国的gopher提供了一个免费合法的代理goproxy.cn,其已经开源。只需一条简单命令就可以使用该代理:go env -w GOPROXY=https://goproxy.cn,direct五、Go Get
执行go get命令,在下载依赖包的同时还可以指定依赖包的版本。
运行go get -u命令会将项目中的包升级到最新的次要版本或者修订版本;
运行go get -u=patch命令会将项目中的包升级到最新的修订版本;
运行go get [包名]@[版本号]命令会下载对应包的指定版本或者将对应包升级到指定的版本。
提示:go get [包名]@[版本号]命令中版本号可以是 x.y.z 的形式,
例如 go get foo@v1.2.3,也可以是 git 上的分支或 tag,例如 go get foo@master,还可以是 git 提交时的哈希值,例如 go get foo@e3702bed2。
六、godep
godep 是一个Go语言官方提供的通过 vender 模式来管理第三方依赖的工具,类似的还有由社区维护的准官方包管理工具 dep。
Go语言从 1.5 版本开始开始引入 vendor 模式,如果项目目录下有 vendor 目录,那么Go语言编译器会优先使用 vendor 内的包进行编译、测试等。
6.1 安装godepgo get github.com/tools/godep命令执行成功后会将 godep 工具的源码下载到 GOPATH 的 src 录下对应的文件夹中,同时还会在 GOPATH 的 bin 目录下生成一个名为 godep.exe 的可执行文件。
6.2 配置环境变量
6.3 godep基本命令
命令 说明godep save 将依赖包的信息保存到Godeps.json文件中 godep go 使用保存的依赖项运行go工具 godep get 下载并安装指定的包 godep path 打印依赖的GOPATH路径 godep restore 在GOPATH中拉取依赖的版本 godep update 更新选定的包或go版本 godep diff 显示当前和以前保存的依赖项集之间的差异 godep version 查看版本信息6.4 使用godep
执行godep save命令,会在当前目录中创建 Godeps 和 vender 两个文件夹。
Godeps 文件夹下会生成一个 Godeps.json 文件,用来记录项目中所依赖的包信息;vender 目录则是用来保存当前项目所依赖的所有第三方包。生成的 Godeps.json 文件的结构如下所示:{
"ImportPath": "main",//项目路径信息
"GoVersion": "go1.13",//go语言版本号
"GodepVersion": "v80",//godep版本号
"Deps": [//当前引用的包
{
"ImportPath": "github.com/go-gomail/gomail",//依赖包路径
"Comment": "2.0.0-23-g81ebce5",//版本号
"Rev": "81ebce5c23dfd25c6c67194b37d3dd3f338c98b1"//哈希值
}
]
}
当所引用的第三方包要升级只需要修改Godep.json里面的依赖包的版本号,让后执行godep save命令即可。
godep查找依赖顺序: 在项目路径下的vender文件夹中查找 到GOPATH/src目录查找 查看全部
GOROOT指的Golang语言的安装路径,即Golang语言内置程序库所在的位置。通常在安装时环境变量会设置好GOROOT路径。当开发时,import标准库时并不需要额外安装,当程序运行后,也会去GOROOT路径下寻找相应程序。
二、GOPATH
GOPATH即存放第三方库的位置。通常开发时,会把GOPATH重新设置。
2.1 GOPATH目录
bin:放置编译后生成的可执行文件。
pkg:放置编译后生成的包/库的归档文件
src:放置项目和库的源文件;
2.1.1 src
用于以包(package)的形式组织并存放 Go 源文件,这里的包与 src 下的每个子目录是一一对应。例如,若一个源文件被声明属于 log 包,那么它就应当保存在 src/log 目录中。
并不是说 src 目录下不能存放 Go 源文件,一般在测试或演示的时候也可以把 Go 源文件直接放在 src目录下,但是这么做的话就只能声明该源文件属于 main 包了。正常开发中还是建议大家把 Go 源文件放入特定的目录中。
另外需要注意的是,Go语言会把通过go get命令获取到的库源文件下载到 src 目录下对应的文件夹当中。
2.1.2 pkg
用于存放通过go install命令安装某个包后的归档文件。归档文件是指那些名称以“.a”结尾的文件。
该目录与 GOROOT 目录(也就是Go语言的安装目录)下的 pkg 目录功能类似,区别在于这里的 pkg 目录专门用来存放项目代码的归档文件。
编译和安装项目代码的过程一般会以代码包为单位进行,比如 log 包被编译安装后,将生成一个名为 log.a 的归档文件,并存放在当前项目的 pkg 目录下。
2.1.3 bin
与 pkg 目录类似,在通过go install命令完成安装后,保存由 Go 命令源文件生成的可执行文件。在类 Unix 操作系统下,这个可执行文件的名称与命令源文件的文件名相同。
而在 Windows 操作系统下,这个可执行文件的名称则是命令源文件的文件名加 .exe 后缀。
2.2 设置和使用GOPATH
2.2.1 windows设置
在环境变量中添加GOPATH变量,将目录添加即可。
2.2.2 linux设置
设置当前目录为GOPATH:选择一个目录,在目录的命令行下执行
export GOPATH='pwd'
2.3 GOPATH缺点
只要第三方库不是官方程序库,都要放置到$GOPATH/src下才可以使用.
三 Go Modules
Golang从1.13版本开始有Go Modules.
3.1 使用Go Modules的好处
Go Modules可以将某个项目(文件夹)下的所有依赖整理成一个 go.mod 文件,里面写入了依赖的版本等 使用Go Modules之后我们可不用将代码放置在src下了
3.2 使用Go Modules
官方github关于Modules的WIKI:https://github.com/golang/go/wiki/Modules
使用 Go Modules 管理依赖后会在项目根目录下生成两个文件 go.mod 和 go.sum go.mod会记录当前项目的所有依赖项module test go 1.15 require http://github.com/gin-gonic/gin v1.6.3go.sum
会记录每个依赖库的版本和哈希值
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=3.3 如何开启Go Modules
要使用Go Modules首先要设置Go111Modules = on, GO111MODULE有三个值 on:开启 off:关闭 auto根据当前目录下是否有go.mod文件来判断是否使用modules功能
注意:**无论使用那种模式,module功能默认不在GOPATH目录下查找依赖文件,所以使用modules功能时请设置好代理
设置
GO111MODULE
# windows set GO111MODULE=on
# linux export GO111MODULE=on
然后使用go env查看
3.4 初始化Go Modules进入项目文件夹test
# 初始化路径 go mod init test
# 检测依赖 go mod tidy
# 如果有些依赖项未下载则需要下载 go mod download
# 导入依赖 go mod vendor3.5 GoLand开启Go Modules
文件(File) 设置(Setting) 在GO选项下选择GO MODULES 启用Go Modules 设置代理服务器
3.6 更新依赖# 检测依赖 go mod tidy # 如果有些依赖项未下载则需要下载 go mod download # 导入依赖 go mod vendor3.7 Git使用GO MODULES注意事项
在git中需要把vendor文件夹放入白名单中,不然项目体积会很大。 git设置白名单方式为在git托管的项目根目录新建 .gitignore 文件,设置忽略即可,但是 go.mod 和 go.sum 不要忽略。
另一人clone项目后在本地进行依赖更新(同上方依赖更新)即可
3.8 Go Module常用命令go mod init
# 初始化go.mod go mod tidy
# 更新依赖文件 go mod download
# 下载依赖文件 go mod vendor
# 将依赖转移至本地的vendor文件 go mod edit
# 手动修改依赖文件 go mod graph
# 打印依赖图 go mod verify
# 校验依赖 go mod why
# 解释为什么需要依赖四、GO PROXY
GOPROXY 是Go语言官方提供的一种通过中间代理商来为用户提供包下载服务的方式。要使用 GOPROXY 只需要设置环境变量 GOPROXY 即可。
4.1 国内镜像
// 阿里云镜像
GOPROXY=https://mirrors.aliyun.com/goproxy/ // 中国golang镜像
GOPROXY=https://goproxy.io
// 七牛云为中国的gopher提供了一个免费合法的代理goproxy.cn,其已经开源。只需一条简单命令就可以使用该代理:go env -w GOPROXY=https://goproxy.cn,direct五、Go Get
执行go get命令,在下载依赖包的同时还可以指定依赖包的版本。
运行go get -u命令会将项目中的包升级到最新的次要版本或者修订版本;
运行go get -u=patch命令会将项目中的包升级到最新的修订版本;
运行go get [包名]@[版本号]命令会下载对应包的指定版本或者将对应包升级到指定的版本。
提示:go get [包名]@[版本号]命令中版本号可以是 x.y.z 的形式,
例如 go get foo@v1.2.3,也可以是 git 上的分支或 tag,例如 go get foo@master,还可以是 git 提交时的哈希值,例如 go get foo@e3702bed2。
六、godep
godep 是一个Go语言官方提供的通过 vender 模式来管理第三方依赖的工具,类似的还有由社区维护的准官方包管理工具 dep。
Go语言从 1.5 版本开始开始引入 vendor 模式,如果项目目录下有 vendor 目录,那么Go语言编译器会优先使用 vendor 内的包进行编译、测试等。
6.1 安装godepgo get github.com/tools/godep命令执行成功后会将 godep 工具的源码下载到 GOPATH 的 src 录下对应的文件夹中,同时还会在 GOPATH 的 bin 目录下生成一个名为 godep.exe 的可执行文件。
6.2 配置环境变量
6.3 godep基本命令
命令 说明godep save 将依赖包的信息保存到Godeps.json文件中 godep go 使用保存的依赖项运行go工具 godep get 下载并安装指定的包 godep path 打印依赖的GOPATH路径 godep restore 在GOPATH中拉取依赖的版本 godep update 更新选定的包或go版本 godep diff 显示当前和以前保存的依赖项集之间的差异 godep version 查看版本信息6.4 使用godep
执行godep save命令,会在当前目录中创建 Godeps 和 vender 两个文件夹。
Godeps 文件夹下会生成一个 Godeps.json 文件,用来记录项目中所依赖的包信息;vender 目录则是用来保存当前项目所依赖的所有第三方包。生成的 Godeps.json 文件的结构如下所示:
{
"ImportPath": "main",//项目路径信息
"GoVersion": "go1.13",//go语言版本号
"GodepVersion": "v80",//godep版本号
"Deps": [//当前引用的包
{
"ImportPath": "github.com/go-gomail/gomail",//依赖包路径
"Comment": "2.0.0-23-g81ebce5",//版本号
"Rev": "81ebce5c23dfd25c6c67194b37d3dd3f338c98b1"//哈希值
}
]
}
当所引用的第三方包要升级只需要修改Godep.json里面的依赖包的版本号,让后执行godep save命令即可。
godep查找依赖顺序: 在项目路径下的vender文件夹中查找 到GOPATH/src目录查找
Go的包管理比python烂得多,不知道为啥还要被吹捧
python • 李魔佛 发表了文章 • 0 个评论 • 2072 次浏览 • 2021-08-07 23:53
GO111MODULE与GOPATH不兼容
2. 竟然要搞动系统的环境变量。
主要本人使用vim开发,编译运行都在shell底下,windows也是在cmd下跑的
3. 下载包的地址被墙,需要设置国内的地址。并且官方的包镜像也在github,其下载速度,你懂的。
蜗牛一样的。 查看全部
GO111MODULE与GOPATH不兼容
2. 竟然要搞动系统的环境变量。
主要本人使用vim开发,编译运行都在shell底下,windows也是在cmd下跑的
3. 下载包的地址被墙,需要设置国内的地址。并且官方的包镜像也在github,其下载速度,你懂的。
蜗牛一样的。
30天掌握Golang 教程系列 第一课 基础知识
量化交易-Ptrade-QMT • 量化大师 发表了文章 • 0 个评论 • 2219 次浏览 • 2021-08-04 01:15
这里有一个Golang的练习库,输入基础入门的资料。 大家可以先练习练习:
https://github.com/Rockyzsu/GolangLearning/tree/master/Go-Notes
基础语法是没办法绕过的,如果前期不打扎实,后期也会不断来回折腾。除非你做的项目只是一次性的,否则,磨刀不误砍柴工,还是打扎实。 把上面的github的例子弄懂,这个Go-notes的好处是,如果遇到你不懂的,可以马上查找相关的资料。如果全部都懂的话,可以进阶到第二阶段。
个人觉得还是得要多看看别人的代码,看多了,其实你写代码也会有灵感。(虽然有些人写的代码很烂,但是也可以自己做过标号,避免自己以后写出同样的代码。)
PS: 本来我想从0开始写教程,不过网上其实也有很多教程,很多视频。 也有不少的书籍可以学。所以就没有必要重复造轮子了。
而实际的情况是,入门的人数需求是100个人,而进阶的需求是只有60个人,而深入理解并需要对应的教程的,可能只有20人不到。
所以想着写golang教程,最受欢迎的其实是hello world教程。
实际写起来也很容易,无法就是if - else,for, 切片,数组,通道,goroutine,结构体等。
不过对于笔者的能力提升是没有一点点用处的,当日提升知名度除外。
所以入门系列的基础课,我这里就一比带过。可以留一些比较容易踩到的坑。
当然这个基础知识不可能 第一天就全部搞定。 可以多花几天甚至一周的时间。
查看全部
这里有一个Golang的练习库,输入基础入门的资料。 大家可以先练习练习:
https://github.com/Rockyzsu/GolangLearning/tree/master/Go-Notes
基础语法是没办法绕过的,如果前期不打扎实,后期也会不断来回折腾。除非你做的项目只是一次性的,否则,磨刀不误砍柴工,还是打扎实。 把上面的github的例子弄懂,这个Go-notes的好处是,如果遇到你不懂的,可以马上查找相关的资料。如果全部都懂的话,可以进阶到第二阶段。
个人觉得还是得要多看看别人的代码,看多了,其实你写代码也会有灵感。(虽然有些人写的代码很烂,但是也可以自己做过标号,避免自己以后写出同样的代码。)
PS: 本来我想从0开始写教程,不过网上其实也有很多教程,很多视频。 也有不少的书籍可以学。所以就没有必要重复造轮子了。
而实际的情况是,入门的人数需求是100个人,而进阶的需求是只有60个人,而深入理解并需要对应的教程的,可能只有20人不到。
所以想着写golang教程,最受欢迎的其实是hello world教程。
实际写起来也很容易,无法就是if - else,for, 切片,数组,通道,goroutine,结构体等。
不过对于笔者的能力提升是没有一点点用处的,当日提升知名度除外。
所以入门系列的基础课,我这里就一比带过。可以留一些比较容易踩到的坑。
当然这个基础知识不可能 第一天就全部搞定。 可以多花几天甚至一周的时间。
vim定义快捷键 运行go程序
Linux • 李魔佛 发表了文章 • 0 个评论 • 2150 次浏览 • 2021-07-23 16:27
nnoremap gr :!go run %<CR>
所以你可以很容易地输入gr你的vim,它就会执行。
nnoremap gr :!go run %<CR>
所以你可以很容易地输入gr你的vim,它就会执行。