xyecho - just my notes 2024-06-11T08:19:32+00:00 1447675994@qq.com golang painc 发生了 2024-04-11T09:08:12+00:00 kane http://blog.xyecho.com/golang-panic
	Config1 := mapConf["game"].(map[string]interface{})
	for key, value := range confMap {
		Config1[key] = value
	}

mapConf[“game”]为nil:如果mapConf[“game”]是 nil,那么在尝试进行类型断言时也会导致 panic。

改成:

Config1 := make(map[string]interface{})
	for key, value := range confMap {
		Config1[key] = value
	}
	mapConf["game"] = Config1
]]>
vscode 插件列表 2024-04-09T21:00:30+00:00 kane http://blog.xyecho.com/vscode-plug-in-list 常有插件

1、Draw.io Integration : https://marketplace.visualstudio.com/items?itemName=hediet.vscode-drawio 2、Git Graph https://marketplace.visualstudio.com/items?itemName=mhutchie.git-graph 3、sonhero.io tools for VS Code: https://marketplace.visualstudio.com/items?itemName=JSONHero.jsonhero-vscode 4、AI Coding Autocomplete codeium https://marketplace.visualstudio.com/items?itemName=Codeium.codeium 5、Project Manager https://marketplace.visualstudio.com/items?itemName=alefragnani.project-manager 6、golang https://marketplace.visualstudio.com/items?itemName=golang.Go 7、 Markdown Preview Enhanced https://marketplace.visualstudio.com/items?itemName=shd101wyy.markdown-preview-enhanced

Tutorial :https://shd101wyy.github.io/markdown-preview-enhanced/#/zh-cn/

配置

1、https://github.com/kakabei/configbox/tree/main/vscode

]]>
golang time.AddDate的问题 2024-04-01T20:08:12+00:00 kane http://blog.xyecho.com/golang-time-adddate 周末线上出现一个问题,3月份的订单没有算出来,从数据库表数据上看,订单数据已经是完成状态,但数据为空。

业务上的逻辑是,每天会计算上个月的订单和当月的订单和。一月的订单周期是一个有1日12点到下个月的1日12点。

如前当3月31日,上个月的周期是2月1日12点到3月1日12点;本月的周期是3月1点12到当前时间点。

逻辑在处理上个月的订单时用了 AddDate

lastMonth := time.AddDate(0, -1, 0).Format("200601")

问题就出现在这里。 当前时间是3月31时,time.AddDate(0, -1, 0) 之后,是 20240302 ,还是3月份,并不符合预期。

如下代码:

package main

import (
	"fmt"
	"time"
)

func main() {

	today := time.Date(2024, 2, 29, 0, 0, 0, 0, time.Local)
	nextDay := today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 3, 31, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 4, 30, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 5, 31, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 6, 30, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 7, 31, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 8, 31, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 9, 30, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 10, 31, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 11, 30, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 12, 31, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

}

输出:

today :20240229 nextDay :20240129
today :20240331 nextDay :20240302
today :20240430 nextDay :20240330
today :20240531 nextDay :20240501
today :20240630 nextDay :20240530
today :20240731 nextDay :20240701
today :20240831 nextDay :20240731
today :20240930 nextDay :20240830
today :20241031 nextDay :20241001
today :20241130 nextDay :20241030
today :20241231 nextDay :20241201

其中,如 20240331、20240531、20240731、20241031 这一些时算的上月时间就出错,它依然是本月的时间。

解决这个问题最简单,最快的方式是引用库 https://github.com/Andrew-M-C/go.timeconv

package main

import (
	"fmt"
	"time"
	"github.com/Andrew-M-C/go.timeconv"
)

func main() {
	t := time.Date(2019, 1, 31, 0, 0, 0, 0, time.UTC)
	nt := t.AddDate(0, 1, 0)	// Add one month
	fmt.Printf("%v\n", nt)		// 2019-03-03 00:00:00 +0000 UTC, not expected

	nt = timeconv.AddDate(t, 0, 1, 0)
	fmt.Printf("%v\n", nt)		// 2019-02-28 00:00:00 +0000 UTC
}

1、令人困惑的 Go time.AddDate https://learnku.com/articles/71760

2、Go time 包中的 AddDate 的逻辑避坑指南 https://cloud.tencent.com/developer/article/1803695

]]>
常用命令 git 2024-04-01T19:21:12+00:00 kane http://blog.xyecho.com/frequently-used-command-reference-git 撤销修改

一、未使用 git add 缓存代码

撤销指定文件:

git checkout -- filepathname

撤销所有的文件修改可以使用 

git checkout .

对新建文件无效

二、已经使用了  git add 缓存了代码

撤销指定文件:  

git reset HEAD filepathname

撤销所有的文件修改可以使用  

git reset HEAD .

清除 git  对于文件修改的缓存。相当于撤销 git add 命令所在的工作。

三、已经用 git commit  提交了代码

来回退到上一次commit的状态 :

git reset --hard HEAD^ 

此命令可以用来回退到任意版本:

git reset --hard  commitid

分支

git fetch --prune  # 刷新本地和远程一样

git branch -d 分支名  #  删除本地分支

git checkout -b fix-instance-count origin/main  # 在本地创建一个分支,同时把远程的分支同步下来

git push -u origin new-branch   # 把分支同步到远程仓库

git 提交一个分支,发现远程已经被删除,如何再次提交可以用 :

git push origin develop_2.0.4

Git 撤销合并——如何在 Git 中恢复之前的合并提交

创建切换分支:

git ckeckout  -b feature/1.15.1-kane

提交分支

git push origin feature/1.15.1-kane 

合并分支,把本地的分支 feat1 合并到 feat2 中去

git checkout feat2          #  更新  feat2 分支
git merge feat1             # 合并 feat1 到  feat2
git push origin feat2       # 推送 feat2

基于 Merge Request 的开发流程 :https://wikinote.gitbook.io/git-learning/gitlab-cao-zuo/gitlab-merge-request

如何撤销 Merge Request?https://wikinote.gitbook.io/git-learning/gitlab-cao-zuo/gitlab-merge-request-revert

]]>
常用命令 curl 2024-04-01T19:21:12+00:00 kane http://blog.xyecho.com/frequently-used-command-reference-curl curl 常见的技巧

github 地址:https://github.com/curl/curl

参数:

-o <file>    # --output: 写入文件
-u user:pass # --user: 验证
-v           # --verbose: 在操作期间使 curl 冗长
-vv          # 更冗长
-s           # --silent: 不显示进度表或错误
-S           # --show-error: 与 --silent (-sS) 一起使用时,显示错误但没有进度表
-i           # --include: 在输出中包含 HTTP 标头
-I           # --head: 仅标头

数据:

# --data: HTTP post 数据
# URL 编码(例如,status="Hello")
-d 'data'

# --data 通过文件
-d @file

# --get: 通过 get 发送 -d 数据
-G

头信息 Headers:

-A <str>     # --user-agent
-b name=val  # --cookie

# 从 URL 的指定文件加载 cookie
-b, --cookie FILE
# 将 cookie 从 URL 保存到指定文件
-c, --cookie-jar FILE

-b FILE          # --cookie
-H "X-Foo: y"    # --header
--compressed     # 使用 deflate/gzip 

ssl :

    --cacert <file>
    --capath <dir>
-E, --cert <cert>     # --cert: 客户端证书文件
    --cert-type       # der/pem/eng
-k, --insecure        # 对于自签名证书

示例

1、GET 请求

curl -I https://www.baidu.com                                          # curl 发请求
curl -v -I https://www.baidu.com                                       # 带有详细信息的 curl 发请求
curl -X GET https://www.baidu.com                                      # 使用显式 http 方法进行 curl
curl --noproxy 127.0.0.1 http://www.stackoverflow.com                  # 没有 http 代理的 curl
curl --connect-timeout 10 -I -k https://www.baidu.com                  # curl 默认没有超时
curl --verbose --header "Host: www.mytest.com:8182" www.baidu.com      # curl 得到额外的标题
curl -k -v https://www.google.com                                      # curl 获取带有标题的响应

2、POST 请求

url -d "name=username&password=123456" <URL>    # curl 发请求
curl <URL> -H "content-type: application/json" -d "{ \"woof\": \"bark\"}"    # curl 发送 json

3、高级用法

curl -L -s http://ipecho.net/plain, curl -L -s http://whatismijnip.nl            # 获取我的公共 IP撒··
curl -u $username:$password http://repo.dennyzhang.com/README.txt                # 带凭证的 curl
curl -v -F key1=value1 -F upload=@localfilename <URL>                            # curl 上传
curl -k -v --http2 https://www.google.com/                                       # 使用 http2 curl
curl -T cryptopp552.zip -u test:test ftp://10.32.99.187/                         # url ftp 上传
curl -u test:test ftp://10.32.99.187/cryptopp552.zip -o cryptopp552.zip    curl  # ftp 下载
curl -v -u admin:admin123 --upload-file package1.zip http://mysever:8081/dir/package1.zip    # 使用凭证 curl 上传

4、查询当前机器的出口IP

 (base) C:\tools> curl cip.cc
IP      : 121.12.81.78
地址    : 中国  广东  江门
运营商  : 电信

数据二  : 广东省深圳市 | 电信

数据三  : 中国广东省深圳市 | 电信
URL     : http://www.cip.cc/121.12.81.78

]]>
python mysql 插入更新一些特殊的字符 2024-03-09T09:08:12+00:00 kane http://blog.xyecho.com/python-mysql-connector 写了一个脚本,把一个mysql 表的中数据从一个表更新到另一个表中。其他有字段是路径,包含有 /' 等字符。

第一次的做法是:

    sql = "update t_softname set icon=%s, start_cmd=%s where name=%s".format(icon, link, name)
    cursor.execute(sql) 

却发现了问题,就是在遇到特殊的字符会被转义。如:写入的路径后会没了斜杠 \。或遇到 ' 出现 sql 解析异常。

这是字符串被转义导致的。

使用参数化查询才可以,如下:


    sql = "update t_softname set icon=%s, start_cmd=%s where name=%s"
    cursor.execute(sql,(icon, link, name))  
]]>
go-zero swagger 的使用 2024-03-09T09:08:12+00:00 kane http://blog.xyecho.com/go-zore-swagger Swagger 是一个开源的 API 设计工具,它帮助开发者设计、构建、记录和使用RESTful Web服务。Swagger的核心是 OpenAPI 规范。

官网:(https://swagger.io/)[https://swagger.io/]

主要特点:

  • 自动化文档生成:Swagger可以自动从代码注释和API定义生成API文档,这些文档可以被人类阅读,也可以被机器解析。
  • 交互式API测试:Swagger UI提供了一个交互式的界面,允许开发者直接在浏览器中测试API,而无需编写代码。

s

]]>
go-zero 日志输出的问题 2024-03-09T09:08:12+00:00 kane http://blog.xyecho.com/go-zore-log-problem go-zore 日志输出方式体验让我有一些不适。

今天还遇到一个现象,日志输出如下:

{"@timestamp":"2024-03-09T15:48:08.026+08","caller":"server/Helper.go:164","content":"httpc.Do err userId[512] host[http://127.0.0.1:8888/xxxxx/xxxxxxList?offset=0\u0026limit=10\u0026order=desc\u0026sortby=create_time\u0026state=-1\u0026states=0,1,2,3,4\u0026biz_id=0\u0026agent_id=512]","level":"error","span":"66a2ba1882458680","trace":"c94c9ac8179690d592fc348b40666e16"}

出一些 \u0026 之类的。 但如果把 Encoding 设置为 plain,则正常。

2024-03-09T15:47:08.006+08       error  httpc.Do err userId[512] host[http://127.0.0.1:8888/xxxxx/xxxxxxList?offset=0&limit=10&order=desc&sortby=create_time&state=-1&states=0,1,2,3,4&biz_id=0&agent_id=512]      caller=server/Helper.go:164        trace=ca5e1ad81e7d0528f38b361c63a75f35  span=48b14f5d8bce91e9
]]>
go-zero httpc.Do post 数据因 struct 继承导致的失败 2024-03-09T09:08:12+00:00 kane http://blog.xyecho.com/go-zore-struct-httpc-do-problem 工作时遇到的一个问题。

背景大概可以简化为:请求不同服务过来的数据后做聚合,然后转发另一个服务。

对于数据的处理习惯性就是:


// data from server A 
type BaseB struct {
	Offset int64 `json:"offset"`
	Limit  int64 `json:"limit"`
}

// data from server B 
type BaseB struct {
	Id    int64 `json:"id"`
    Name string `json:"name"`
	  
}

// send to server C
type BaseC  struct {
	BaseA
	BaseB
    Addr  string `json:"addr"`
}

baseC := new(BaseC)
baseC.Offset = 199
baseC.Id = 1
baseC.Name = "kane"
baseC.Addr = "guangdong"
fmt.Printf("baseC ----- > %+v\n", baseC)

这里对 BaseC 成员变量的操作和它继承的BaseB、BaseB 的成员一样,都按 BaseC的成员一样处理。

但是,在 fmt.Printf baseC 时,baseC 的结构却有点和想像中不一样。而是:

 baseC ----- > &{BaseA:{Offset:199 Limit:0} BaseB:{Id:1 Name:kane} Addr:guangdong}

中包含了 “BaseA” “BaseB”。

多想一步,把这个结构体转 json 输出,如下:

baseCByte ----- > {"offset":199,"limit":0,"id":1,"name":"kane","addr":"guangdong"}

想像上面 baseC 数据的结构应该是这样的。但事实却不一样。

自己 golang 的底层知识不够导致的。

go-zore 的 httpc.Do()在 post 数据带上设置头信息时,https://go-zero.dev/docs/tutorials/http/client/index

func main() {
    flag.Parse()

    req := Request{
        Node:   "foo",
        Header: "foo-header",
        Foo: "foo",
        Bar: "bar",
    }
    resp, err := httpc.Do(context.Background(), http.MethodPost, *domain+"/nodes/:node", req)
    if err != nil {
        fmt.Println(err)
        return
    }

    io.Copy(os.Stdout, resp.Body)
}

Request 用了继承的方式: 如:

type Body struct {
    Foo    string `json:"foo"`
    Bar    string `json:"bar"`
}
    
type Request struct {
    Body
    Header string `header:"X-Header"`
}

发送过去之后, Body 成了空的。估计就是继承无法正确解析的原因。

]]>
golang 开发备忘 2024-01-02T10:12:15+00:00 kane http://blog.xyecho.com/golang-note golang 资料

Go 语言高性能编程 : https://geektutu.com/post/high-performance-go.html?continueFlag=d5490667caa63d66b43697894ac52925

golang 笔记

]]>