- Created by 郭强, last modified by 智刚 on Nov 17, 2023
You are viewing an old version of this page. View the current version.
Compare with Current View Page History
« Previous Version 75 Next »
寄语:欢迎大家积极参与编辑,把自己遇到的坑怎么填的记录起来。众人拾柴火焰高
一、Golang基础
1、程序产生异常,但是程序直接崩溃未被框架自动捕获
使用GoFrame
框架是严谨和安全的,如果程序产生了异常,会默认被框架捕获。如果未被自动捕获,那么可能是由于程序逻辑自行开了新的goroutine
,在新的goroutine
中产生了异常。因此这里有两个方案可供大家选择:
- 不建议在请求中再开
goroutine
来处理请求,这样或使得goruotine
快速膨胀,当goroutine
多了之后也会在Go
引擎层面影响程序的整体调度。 - 如果实在有必要新开
goroutine
的场景下,可以考虑使用grpool.AddWithRecover
来创建新的goroutine
,见名知意,它会自动捕获异常。更详细的介绍请参考:协程管理-grpool
2、json
输出时屏蔽掉一些字段
可以通过结构体嵌套的方式实现,通过使用*struct{}
类型不占用空间以及omitempty
字段为空不输出字段的特性
type User struct { Pwd string `json:"pwd"` Age int `json:"age"` } type UserOut struct { User Pwd *struct{} `json:"pwd,omitempty"`// 这里的字段json名需要和嵌套的字段json名一致,否则无效 } func TestJson(t *testing.T) { u := User{Pwd: "123", Age: 1} bb := UserOut{User: u} b, _ := json.MarshalIndent(bb, "", " ") t.Log(string(b)) }
二、兼容性相关
1、client_tracing.go:73:3: undefined: attribute.Any
以下错误:
D:\Program Files\Go\bin\pkg\mod\github.com\gogf\gf@v1.16.6\net\ghttp\internal\client\client_tracing.go:73:3: undefined: attribute.Any D:\Program Files\Go\bin\pkg\mod\github.com\gogf\gf@v1.16.6\net\ghttp\internal\client\client_tracing_tracer.go:150:3: undefined: attribute.Any D:\Program Files\Go\bin\pkg\mod\github.com\gogf\gf@v1.16.6\net\ghttp\internal\client\client_tracing_tracer.go:151:3: undefined: attribute.Any
导致该错误的原因在于目前您正在使用的goframe
依赖的otel
包版本过低(otel
包是OpenTelemetry
使用Golang
实现的第三方包,比较常用,很多第三方基础组件都会依赖),而项目中其他的第三方依赖的otel
包过高,按照Golang module
的管理策略,项目将会使用最新的otel
包,于是导致了版本不兼容。
根因还是在于otel
的包在迭代中出现了不兼容升级导致,不过目前otel
包已经较稳定,出现不兼容的可能性降低。
解决的办法是只有升级goframe
的版本,goframe
最新版本已经更新使用了稳定的otel
包。如果您使用的已经是v1
的最新版本(v1.16
),那么请升级为v2
版本解决。
2、使用gf
依赖v1.16.2
时go mod tidy
失败
found (v0.36.0), but does not contain package go.opentelemetry.io/otel/metric/registry
解决办法,升级gf
依赖到v1.16.9
再go mod tidy
三、数据库相关
1、update/insert
操作不生效
使用orm
时,配置文件中:
dryRun = "(可选)ORM空跑(只读不写)"
这行配置一定要删掉或者设置为0
否则出现update insert
操作不生效的现象。具体请参考文档:ORM高级特性
2、cannot find database driver for specified database type "xxx", did you misspell type name "xxx" or forget importing the database driver?
程序代码没有引入依赖的数据库驱动,需要注意从GoFrame v2.1
版本开始,需要手动引入社区驱动,请参考:
3、数据库打开DEBUG
日志后,查询的SQL
语句中发现出现 WHERE 0=1
的语句
出现 WHERE 0=1
的情况是由于查询条件中存在数组条件,并且数组的长度为0
。这种情况ORM
无法自动过滤这种空数组条件(这种条件过滤可能会引起业务异常),需要开发者根据业务场景,显示调用OmitEmpty
或者OmitEmptyWhere
来告诉ORM
可以过滤这些空数组的条件。4、MYSQL中的表情,用SQL查询后,乱码问题
解决办法:
config.toml
文件 数据库配置的charset
设置为utf8mb4
默认是utf8
MySQL
存储表情时注意:
- 数据库编码
utf8mb4
- 表的编码是
utf8mb4
- 表中内容字段是
utf8mb4
四、使用相关
1、不同环境如何,加载不同的配置文件?
不同环境指的是:开发环境/测试环境/预发环境/生产环境等。
- 首先,在一些互联网项目中,特别是分布式或者微服务化的架构下,一般会使用配置管理中心,不同的环境会对应不同的配置管理中心,所以这样的场景不会存在这样的问题。
其次,如果是传统的项目管理方式下,可能会将配置文件放到代码仓库中共同管理,这样的方式是不推荐的。如果您仍然想要这么做,您可以通过系统环境变量或者命令行启动参数,让程序自动选择配置文件或者指定配置目录,参考 配置管理 章节。例如:
./app --gf.gcfg.file config-prod.toml
则通过命令行启动参数的方式将默认读取的配置文件修改为了config-prod.toml
文件。我们不建议您在程序中通过代码逻辑来区分和读取不同环境的配置文件。
2、glog with "ERROR: logging before flag.Parse"
Golang
官方有个简单的日志库包名也叫做glog
,检查你文件顶部import
的包名,将github.com/golang/glog
修改为框架的日志组件即可,日志组件使用请参考:日志组件
3、gcron
与http
如何同时使用?
func main() { //定时任务1 gcron.AddSingleton("*/5 * * * * *", func() { task.Test() glog.Debug("gcron1") }) //定时任务2 gcron.AddSingleton("*/10 * * * * *", func() { glog.Debug("gcron2") }) //接收http请求 g.Server().Run() }
注意, gcron
一定要在g.Server().Run
的前面。
4、GoFrame
的struct tag
(标签) 有哪些?
参数请求、数据校验、OpenAPIv3
、命令管理、数据库ORM。
Tag(简写) | 全称 | 描述 | 相关文档 |
---|---|---|---|
v | valid | 数据校验标签。 | Struct校验-基本使用 |
p | param | 自定义请求参数匹配。 | |
d | default | 请求参数默认值绑定。 | 请求输入-默认值绑定 |
orm | orm | ORM标签,用于指定表名、关联关系。 | |
dc | description | 通用结构体属性描述,ORM和接口都用到。属于框架默认的属性描述标签。 |
其他:
- 命令行结构化管理参数:命令管理-结构化参数
- 框架常用标签标签集中管理到了
gtag
组件下:https://github.com/gogf/gf/blob/master/util/gtag/gtag.go - 在接口文档章节,由于采用了标签形式生成
OpenAPI
文档,因此标签比较多,具体请参考章节:接口文档
5、HTTP Server
出现context cancel
报错
从框架v2.5
版本开始,框架的HTTP Server
的Request
对象将会直接继承与标准库的http.Request
对象,其中就包括其中的context
上下文对象,具体请参考发布记录:v2.5 2023-07-17。当客户端例如浏览器、HTTP Client
取消请求时,服务端会接收到context cancel
操作(context.Done
),但是服务端并不会直接报出context cancel
的错误。这种错误往往在业务逻辑调用了底层的数据库、消息组件等组件时,由这些组件识别到context cancel
操作,将会停止执行并往上抛出context cancel
错误提醒上层已经终止执行。
这是符合标准库设计的行为,客户端终止请求后,服务端也没有继续执行下去的必要。
五、环境相关
1、Linux
下执行 go build main.go
提示连接超时 connection timed out
go: github.com/gogf/gf@v1.14.6-0.20201214132204-c685876e6f67: Get "https://proxy.golang.org/github.com/gogf/gf/@v/v1.14.6-0.20201214132204-c685876e6f67.mod": dial tcp 172.217.160.113:443: connect: connection timed out
解决办法:
export GO111MODULE=on export GOPROXY=https://goproxy.cn
具体请看:
2、Linux
下安装gf
提示命令不存在command not found
./gf install 安装后 执行gf -v 提示gf: command not found 且/usr/bin目录下并没有gf文件 解决方法: 拷贝sh文件到 /usr/bin目录 cp gf /usr/bin 然后执行 gf -v 就会看到 GoFrame CLI Tool v1.15.4, https://goframe.org Install Path: /bin/gf Build Detail: Go Version: go1.16.2 GF Version: v1.15.3 Git Commit: 22011e76dc3e14006936164cc89e2d4c9190a36d Build Time: 2021-03-30 15:43:22
3、Win10
提示gf
命令不存在
解决办法:安装gf.exe
参考:开发工具
4、` mysql ` 批量写入数据库时,出现数据拆分写入
对于go-sql-driver/mysql库在批量插入数据时出现数据拆分的问题,一般有以下几个原因:
1. packet太小导致插入数据被拆分。可以通过增加max_allowed_packet参数来解决:
```go
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&max_allowed_packet=1024000",
user, password, host, port, dbName)
```
2. 使用多个goroutine并发插入数据,导致插入语句被切片拆开。可以限制并发数或者串行插入。
3. 使用预处理语句时,没有正确处理批量插入。应该使用Exec()方法执行每次插入。
4. 服务器参数设置问题,如bulk_insert_buffer_size太小。可以调整MySQL服务器参数。
5. 版本问题。部分老版本驱动存在批量插入问题。可以考虑升级驱动版本。
建议先检查max_allowed_packet参数,以及是否存在并发插入问题。如果问题仍然存在,可以考虑升级驱动版本试试。
另外,在插入数据前可以做一些优化,比如预处理语句,重新连接数据库等,以减少拆包问题。
如何查看mysql 数据库的 ‘bulk_insert_buffer_size’
查看MySQL数据库的 bulk_insert_buffer_size 参数的值,可以通过以下几种方法:
1. 通过SHOW VARIABLES命令:
```sql
SHOW VARIABLES LIKE 'bulk_insert_buffer_size';
```
这将直接查询并返回当前bulk_insert_buffer_size的值。
2. 通过INFORMATION_SCHEMA:
```sql
SELECT * FROM information_schema.global_variables
WHERE variable_name='bulk_insert_buffer_size';
```
3. 从配置文件my.cnf中查看:
```
[mysqld]
bulk_insert_buffer_size=64M
```
4. 从MySQL命令行客户端使用sys schema查看:
```sql
SELECT * FROM sys.global_variables WHERE variable = 'bulk_insert_buffer_size';
```
5. 在MySQL 8.0中,可以使用sysvars或sys变量查看:
```sql
SELECT @@bulk_insert_buffer_size;
```
以上多种方法都可以获取bulk_insert_buffer_size的当前值。
默认情况下,该值的单位为字节,通常设置为64M比较合适。可以根据实际情况调整该值,来优化批量插入的性能。
如何查看mysql 数据库的 ‘max_allowed_packet’ 默认值呢?
查看MySQL数据库的max_allowed_packet参数默认值,可以通过以下几种方式:
1. 使用SHOW VARIABLES命令:
```sql
SHOW VARIABLES LIKE 'max_allowed_packet';
```
直接查询max_allowed_packet的当前值。
2. 从MySQL的配置文件my.cnf中查看:
```
[mysqld]
max_allowed_packet=16M
```
3. MySQL命令行客户端使用sys schema:
```sql
SELECT * FROM sys.global_variables WHERE variable = 'max_allowed_packet';
```
4. 在MySQL 8.0中,使用sysvars系统变量:
```sql
SELECT @@max_allowed_packet;
```
5. 查看MySQL的版本文档,其中会说明不同版本的默认值。
比如MySQL 5.6默认是4M,MySQL 5.7默认是64M。
6. 在MySQL启动日志中也可以找到max_allowed_packet的默认值或设置值。
综合几种方法即可查看到max_allowed_packet默认值。对于提升性能,可以适当调大该值,如设置为128M或256M。
- No labels