-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.json
463 lines (463 loc) · 234 KB
/
index.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
[
{
"uri": "/ai/__index/",
"title": "ai",
"tags": [],
"description": "",
"content": " Finetuning Fine tuning的原理就是利用已知的网络结构和已知的网络参数,修改output层为我们自己的层,微调最后一层前的所有层的参数,加大最后一层的学习率,因为最后一层我们需要重新学习,所以与其它层相比要有相对较大的学习率,这样就有效利用了深度神经网络强大的泛化能力,又免去了设计复杂的模型以及耗时良久的训练,所以fine tuning是当数据量不足时的一个比较合适的选择。 "
},
{
"uri": "/ai/",
"title": "Ais",
"tags": [],
"description": "",
"content": ""
},
{
"uri": "/other/brew/",
"title": "brew-酿制",
"tags": [],
"description": "",
"content": "官网 Homebrew 类似于一个软件中心,你可以理解成 App Store 或者 Google Play 那样的软件商店,只不过,Homebrew 比前者以及 Mac App Store 来说有着更丰富的资源与更高效的管理。 Homebrew Cask,它是一套建立在 Homebrew 基础之上的 OS X 软件安装命令行工具,是 Homebrew 的扩展. homebrew-自家酿酒 formula-配方 key-桶酒,编译完成的套件资料夹 Cellar-地窖 安装命令 # 如果很慢,可能切换国内源 /bin/bash -c \u0026#34;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\u0026#34; 常用命令 # 在 .zshrc 文件中添加 # Homebrew 取消自动更新 export HOMEBREW_NO_AUTO_UPDATE=true # 安装hugo,nginx,memcached,redis,mongodb-community,mysql,jenkins-lts等等 brew install hugo # 查看 brew info memcached # 搜索 brew search redis # 查看支持的命令 brew commands # 列出常用帮助 brew help # 运行后台服务 start restart stop brew services start nginx #unbound is a validating, recursive, caching DNS resolver. brew services start unbound # unrar已经被删除了,只能安装私人的 brew install unrar brew install carlocab/personal/unrar 附录 HOMEBREW_NO_INSTALL_CLEANUP参数说明\nUnless HOMEBREW_NO_INSTALL_CLEANUP is set, brew cleanup will be run for the installed formulae or, every 30 days, for all formulae brew install xxx过程\nsequenceDiagram actor b as brew actor f as github源 actor ph as $Home/Library/Caches/Homebrew actor pc as /opt/homebrew/Cellar actor pb as /opt/homebrew/bin actor p as $PATH b-\u003e\u003ef: 下载 xxx.rb b-\u003e\u003eb: 执行xxx.rb b-\u003e\u003eph: 下载依赖及源码xxx.tar.gz到 b-\u003e\u003eb: 解压编译 b-\u003e\u003epc:编译结果保存到 pc-\u003e\u003epb:软链接 pb--\u003e\u003ep:事先加入到 github源 "
},
{
"uri": "/categories/",
"title": "Categories",
"tags": [],
"description": "",
"content": ""
},
{
"uri": "/golang/context/",
"title": "context",
"tags": [],
"description": "",
"content": "未完待续 classDiagram class Context{ \u003c\u003c interface \u003e\u003e +Deadline() (deadline time.Time, ok bool) +Done() +Err() error +Value(key any) any } Context \u003c|.. emptyCtx Context \u003c|-- valueCtx class valueCtx{ +Context ~key any ~val any } class canceler{ \u003c\u003c interface \u003e\u003e ~cancel(removeFromParent bool, err error) +Done() } canceler \u003c|.. cancelCtx Context \u003c|-- cancelCtx class cancelCtx{ +Context } cancelCtx \u003c|-- timerCtx class timerCtx{ +timer *time.Timer +deadline time.Time } "
},
{
"uri": "/other/docker/",
"title": "docker",
"tags": [],
"description": "",
"content": "官网 The easiest and recommended way to get Docker Compose is to install Docker Desktop. Docker Desktop includes Docker Compose along with Docker Engine and Docker CLI which are Compose prerequisites.\nlinux服务器单独安装docker,就需要单独安装docker-compose.\ndockerfile示意图 containerd示意图 podman集合-开源替代品 阿里云 # 安装docker引擎 yum install docker # 开机启动 service docker start # repos地址 vim /etc/docker/daemon.json { \u0026#34;registry-mirrors\u0026#34;: \u0026#34;https://registry.docker-cn.com\u0026#34;, \u0026#34;live-restore\u0026#34;: true } docker run -d -p 8090:80 docker/getting-started # 容器日志物理目录 /var/lib/docker/containers/ID/ID-json.log # 设置共享内存 docker --shm-size 256m # 安装 elasticsearch docker pull docker.elastic.co/elasticsearch/elasticsearch:7.5.2 # 启动 openjdk 内存空间有要求 docker run -p 9200:9200 -p 9300:9300 -e \u0026#34;discovery.type=single-node\u0026#34; docker.elastic.co/elasticsearch/elasticsearch:7.5.2 # 在linux至少8G,容易跑起来 # 需要继续 docker kibana rancher # brancher 集群-多个项目,项目-多个命令空间 # rancher 主界面-\u0026gt;右下角有个English,点击选择中文 # 单节点安装,重置密码 docker exec -ti \u0026lt;container_id\u0026gt; reset-password # 必须带上-v $HOME/rancher:/var/lib/rancher/,否则跑不起来 # 导致https://192.168.8.108:8091,https://127.0.0.1:8091(不能访问) # rancher启动慢,需要等待片刻就能浏览器访问 # docker logs -f rancher查看容器启动日志 docker run -d --restart=unless-stopped -p 8090:80 -p 8091:443 --privileged -v $HOME/rancher:/var/lib/rancher/ rancher/rancher:latest rEWlGtFhS52EsKIa https://127.0.0.1:8091 常用命令 所有images都压缩在Docker.qcow2里\n#下载安装gerrit docker pull gerritcodereview/gerrit #运行gerrit docker run -ti -p 8080:8080 -p 29418:29418 gerritcodereview/gerrit #docker 安装(周编译,较新但可能bug) docker pull jenkinsci/jenkins chown -R 1000:1000 /root/jenkins_home docker run -d -p 8080:8080 --restart=always -v /root/jenkins_home:/var/jenkins_home --name jenkins jenkins/jenkins # 帮助文档 https://www.w3cschool.cn/jenkins/jenkins-e7bo28ol.html Blue Ocean值得安装 nohup mdbook serve \u0026gt;~/mdbook.nohup 2\u0026gt;\u0026amp;1 \u0026amp; docker run --name some-mysql -v /my/own/datadir:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag #安装gitlab,机器性能要好,否则卡死 docker pull gitlab/gitlab-ce #gerrit是google开源的代码review工具 docker pull gerritcodereview/gerrit docker run -ti -p 8080:8080 -p 29418:29418 gerritcodereview/gerrit # http://localhost:8080 #SonarQube检测代码质量平台 docker pull sonarqube # Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG] # 查看image的产生过程,可以得到dockerfile docker history --no-trunc alpine container容器管理 #默认显示运行的容器 docker ps #显示所有容器 docker ps -a # attach模式, 类似运行于前台的进程,会占据本地的STDIN和STDOUT docker run nginx # detach模式,可以用docker container attach id改为attach模式,类似于后台运行 docker run -d nginx # 与容器的交互 docker run -it id(container id) command 当command运行结束之后,container的状态也变成了exited的状态 docker exec -it id command 当command运行结束之后,container的状态保持running状态不变 docker stop $(docker ps -q) #已经停止的,正在运行的不能删除 docker rm $(docker ps -a -q) image管理 # 注意images docker images --help Usage: docker images [OPTIONS] [REPOSITORY[:TAG]] List images Options: -a, --all Show all images (default hides intermediate images) --digests Show digests -f, --filter filter Filter output based on conditions provided --format string Pretty-print images using a Go template --no-trunc Donot truncate output -q, --quiet Only show image IDs # 删除image为none docker images|grep none|awk \u0026#39;{print $3 }\u0026#39;|xargs docker rmi # 注意image docker image --help Usage: docker image COMMAND Manage images Commands: build Build an image from a Dockerfile history Show the history of an image import Import the contents from a tarball to create a filesystem image inspect Display detailed information on one or more images load Load an image from a tar archive or STDIN ls List images prune Remove unused images pull Pull an image or a repository from a registry push Push an image or a repository to a registry rm Remove one or more images save Save one or more images to a tar archive (streamed to STDOUT by default) tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE volume管理 docker volume --help Usage: docker volume COMMAND Manage volumes Commands: create Create a volume inspect Display detailed information on one or more volumes ls List volumes prune Remove all unused local volumes rm Remove one or more volumes 其他命令 Management Commands: builder Manage builds buildx* Docker Buildx (Docker Inc., v0.8.1) compose* Docker Compose (Docker Inc., v2.3.3) config Manage Docker configs container Manage containers context Manage contexts image Manage images manifest Manage Docker image manifests and manifest lists network Manage networks node Manage Swarm nodes plugin Manage plugins scan* Docker Scan (Docker Inc., v0.17.0) secret Manage Docker secrets service Manage services stack Manage Docker stacks swarm Manage Swarm system Manage Docker trust Manage trust on Docker images volume Manage volumes 私有部署dockerhub # 利用docker公司提供的工具 docker pull registry # -v 主机目录:容器目录,registry存储仓库中镜像到/var/lib/registry docker run -d -p 5000:5000 --restart=always -v /opt/dockerhub:/var/lib/registry registry # 从dockerhub拉取nginx最新版 docker pull nginx # 打上特定hub的标签 docker tag nginx localhost:5000/nginx # 推送nginx到目标hub中去 docker push localhost:5000/nginx # http://主机ip:5000/v2/_catalog 查看信息 # 增加配置,docker默认走https,但是registry默认走http /etc/docker/daemon.json \u0026#34;insecure-registries\u0026#34;:[ \u0026#34;主机:5000\u0026#34; ] jenkins 另一个开源替代品gocd 忘记密码-admin密码未更改情况\ncat ~/.jenkins/secrets/initialAdminPassword 就是初始化密码 访问jenkins页面,输入管理员admin,及刚才的密码; 进入后可更改其他管理员密码; brew 启动不了\n# Bootstrap failed: 5: Input/output error # Error: Failure while executing; `/bin/launchctl bootstrap gui/503 /Users/zzi/Library/LaunchAgents/homebrew.mxcl.jenkins-lts.plist` exited with 5. # 试试 brew services restart jenkins-lts SSH remote hosts配置中Pty一定不能勾选,否则nohup需要sleep才有效 证书是统一管理各种,包括ssh,gitlab等等. Multijob插件用来批量构建工程,过时了,改用\u0026rsquo;parallel\u0026rsquo; step along with \u0026lsquo;BlueOcean\u0026rsquo; can basical Multiple SCMs用来处理多个git/svn仓库构建一个项目 遇到问题 Docker拉取镜像时出现Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: TLS handshake timeout问题 \u0026#34;registry-mirrors\u0026#34;: [\u0026#34;https://bytkgxyr.mirror.aliyuncs.com\u0026#34;,\u0026#34;https://registry.docker-cn.com\u0026#34;,\u0026#34;http://hub-mirror.c.163.com\u0026#34;] golang示例 docker新版本引入多阶段,主要用来优化不同阶段要求不同,例如编译时需要编译工具,但运行时不需要的.运行时只要引入编译产物就可以了.\n# syntax=docker/dockerfile:1 ## Build FROM golang:1.16-buster AS build WORKDIR /app COPY go.mod ./ COPY go.sum ./ RUN go mod download COPY *.go ./ RUN go build -o /docker-gs-ping ## Deploy FROM gcr.io/distroless/base-debian10 WORKDIR / COPY --from=build /docker-gs-ping /docker-gs-ping EXPOSE 8080 USER nonroot:nonroot ENTRYPOINT [\u0026#34;/docker-gs-ping\u0026#34;] docker build -t docker-gs-ping:multistage -f Dockerfile.multistage . python示例 # syntax=docker/dockerfile:1 FROM python:3.8-slim-buster WORKDIR /app COPY requirements.txt requirements.txt RUN pip3 install -r requirements.txt COPY . . CMD [ \u0026#34;python3\u0026#34;, \u0026#34;-m\u0026#34; , \u0026#34;flask\u0026#34;, \u0026#34;run\u0026#34;, \u0026#34;--host=0.0.0.0\u0026#34;] docker tag python-docker:latest python-docker:v1.0.0 minikube-单机版精简k8s 你可以使用 kubectl 命令行工具来启用 Dashboard 访问 kubectl 会使得 Dashboard 可以通过 http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ 访问。\nkubectl proxy "
},
{
"uri": "/golang/echo/",
"title": "echo",
"tags": [],
"description": "",
"content": "memcached中间件 import ( \u0026#34;bytes\u0026#34; \u0026#34;net/http\u0026#34; \u0026#34;sync\u0026#34; \u0026#34;github.com/bradfitz/gomemcache/memcache\u0026#34; \u0026#34;github.com/labstack/echo/v4\u0026#34; ) var memcacheClientMux sync.Mutex var memcacheClient *memcache.Client // TODO,要不要带上http头部,例如:数据类型html/json/js,Date,Cache-control等等 type middleResp struct { http.ResponseWriter isOK bool key string expiration int32 bytes.Buffer } var StoreErrHandler func(error) func (mr *middleResp) writeStore() { if mr.Buffer.Len() \u0026gt; 0 { err := memcacheClient.Set(\u0026amp;memcache.Item{ Key: mr.key, Flags: 0, Expiration: mr.expiration, Value: mr.Bytes(), }) if StoreErrHandler != nil { StoreErrHandler(err) } } } func (mr *middleResp) Write(body []byte) (int, error) { if mr.isOK \u0026amp;\u0026amp; memcacheClient != nil { _, err := mr.Buffer.Write(body) if StoreErrHandler != nil { StoreErrHandler(err) } } return mr.ResponseWriter.Write(body) } func (mr *middleResp) WriteHeader(statusCode int) { mr.isOK = statusCode == http.StatusOK mr.ResponseWriter.WriteHeader(statusCode) } func MemcacheStore(server string, expireSecond int32) func(echo.HandlerFunc) echo.HandlerFunc { memcacheClientMux.Lock() defer memcacheClientMux.Unlock() if memcacheClient == nil { memcacheClient = memcache.New(server) } return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { resp := c.Response() mr := \u0026amp;middleResp{ ResponseWriter: resp.Writer, key: c.Request().RequestURI, expiration: expireSecond, } resp.Writer = mr err := next(c) mr.writeStore() return err } } } func MemcacheWrap(server string, expireSecond int32, handler echo.HandlerFunc) echo.HandlerFunc { return MemcacheStore(server, expireSecond)(handler) } main使用 package main import ( \u0026#34;fmt\u0026#34; \u0026#34;math/rand\u0026#34; \u0026#34;net/http\u0026#34; \u0026#34;github.com/labstack/echo/v4\u0026#34; \u0026#34;github.com/labstack/echo/v4/middleware\u0026#34; ) func main() { e := echo.New() // Middleware e.Use(middleware.Logger()) e.Use(middleware.Recover()) StoreErrHandler = func(err error) { e.Logger.Error(err) } // Routes e.GET(\u0026#34;/echo/string\u0026#34;, stringHandler, MemcacheStore(\u0026#34;127.0.0.1:11211\u0026#34;, 60)) e.GET(\u0026#34;/echo/html\u0026#34;, MemcacheWrap(\u0026#34;127.0.0.1:11211\u0026#34;, 60, htmlHandler)) // Start server e.Logger.Fatal(e.Start(\u0026#34;:1323\u0026#34;)) } // Handler func stringHandler(c echo.Context) error { err := c.String(http.StatusOK, fmt.Sprintf(\u0026#34;\u0026lt;H1\u0026gt;path:%s\u0026lt;/H1\u0026gt;\u0026#34;, c.Path())) if err != nil { return err } return c.String(http.StatusOK, fmt.Sprintf( \u0026#34;\u0026lt;H2\u0026gt;query:%s,rand:%d\u0026lt;/H2\u0026gt;\u0026#34;, c.QueryString(), rand.Int(), )) } // Handler func htmlHandler(c echo.Context) error { err := c.HTML(http.StatusOK, fmt.Sprintf(\u0026#34;\u0026lt;H1\u0026gt;uri:%s\u0026lt;/H1\u0026gt;\u0026#34;, c.Request().RequestURI)) if err != nil { return err } return c.HTML(http.StatusOK, fmt.Sprintf( \u0026#34;\u0026lt;H2\u0026gt;query:%s,rand:%d\u0026lt;/H2\u0026gt;\u0026#34;, c.QueryString(), rand.Int(), )) } nginx转发 ... location /echo { set $memcached_key \u0026#34;$request_uri\u0026#34;; memcached_pass 127.0.0.1:11211; #指示返回为html,方便浏览器直接显示 default_type text/html; error_page 404 502 504 = @echoServer; } location @echoServer { proxy_pass http://127.0.0.1:1323; } ... "
},
{
"uri": "/elastic/",
"title": "elastic",
"tags": [],
"description": "",
"content": "官网 zinc-golang版本替代品 meili-rust版本替代品 docker run --name ms1.0 --restart always -p 9080:7700 -v $(pwd)/meili_data:/meili_data -d getmeili/meilisearch:v1.0 typesense-c++版本替代品,纯内存 安装 elasticsearch,基于Lucene(TM)的开源搜索引擎\nbrew tap elastic/tap brew install elastic/tap/elasticsearch-full brew services start elasticsearch-full curl -X GET http://localhost:9200/ # 查看安装的插件 curl -X GET http://localhost:9200/_cat/plugins docker pull docker.elastic.co/elasticsearch/elasticsearch:8.1.3 docker run -p 9200:9200 -p 9300:9300 -e \u0026#34;discovery.type=single-node\u0026#34; docker.elastic.co/elasticsearch/elasticsearch:8.1.3 名词概念对比\n关系数据库 elasticsearch 库 索引 表 类型 表模式 映射 行 文档 字段 字段 支持类型 字段类型 说明 string 字符串 byte, short, integer, long 数字 float, double 浮点 boolean 布尔 date 日期 采用倒序存储,关键字 \u0026ndash;》[文档1, 文档2, 文档3 \u0026hellip;.],所以能快速搜索\n插入的数据自动地创建类型(type)及其映射(mapping)\n没有事务一致性,采用乐观版本,文档每更新一次,文档元数据中版本号就增加\n传统数据库更关注数据一致性,永久存储等,在于操作数据,es则偏重于快速搜索\n通常用数据库数据初始化es索引\n索引别名理解及应用\n默认端口9200\n查询语法\nLeaf query clauses match,全文搜索,支持text, number, date or boolean\nGET /_search { \u0026#34;query\u0026#34;: { \u0026#34;match\u0026#34;: { \u0026#34;message\u0026#34;: \u0026#34;this is a test\u0026#34; } } } term,精确相等,不要查询text字段\nGET /_search { \u0026#34;query\u0026#34;: { \u0026#34;term\u0026#34;: { \u0026#34;user.id\u0026#34;: { \u0026#34;value\u0026#34;: \u0026#34;kimchy\u0026#34;, \u0026#34;boost\u0026#34;: 1.0 } } } } range\n浏览器插件\nes-client-elasticsearch客户端 Elasticvue-elasticsearch客户端 kibana\n# 注意和elasticsearch版本配对,否则跑不起来 curl -O https://artifacts.elastic.co/downloads/kibana/kibana-7.17.2-darwin-x86_64.tar.gz curl https://artifacts.elastic.co/downloads/kibana/kibana-7.17.2-darwin-x86_64.tar.gz.sha512 | shasum -a 512 -c - tar -xzf kibana-7.17.2-darwin-x86_64.tar.gz cd kibana-7.17.2-darwin-x86_64/ ./bin/kibana # 浏览器访问 http://localhost:5601/ 如果报内存不够,则删除monitoring索引\n"
},
{
"uri": "/other/unity/et/",
"title": "ET框架",
"tags": [],
"description": "",
"content": "游戏热更目前主流的解决方案 分Lua(ulua/slua/xlua/tolua)系\nILRuntime代表的c#系\nET框架介绍 热更采用了基于C#的ILRuntime\n客户端目录结构 "
},
{
"uri": "/golang/regexp/",
"title": "exgexp包",
"tags": [],
"description": "",
"content": " 正则语法 // 连续的汉字字母数字 var maxHanDigitAlphaReg = regexp.MustCompile(`[\\p{Han}[:digit:][:alpha:]]+`) // 单个汉字字母数字 var minHanDigitAlphaReg = regexp.MustCompile(`[\\p{Han}[:digit:][:alpha:]]+?`) "
},
{
"uri": "/other/firefox/",
"title": "firefox",
"tags": [],
"description": "",
"content": " 扩展组件\n实际上zip压缩后,直接改后缀名xpi 注意不能直接压缩整个目录,应该是选择文件压缩,否则认为损坏.估计压缩比解压多一级目录. 现代firefox一般要求认证,扩展组件开发者,否则不能安装与运行 \u0026ldquo;此附件组件无法安装,未通过验证\u0026rdquo;\n打开Firefox浏览器 地址栏输入“about:config” 搜索“xpinstall.signatures.required”设置项,双击改为“false”,重启 再把xpi拖进Firefox窗口便会提示是否安装 优秀插件\nDark Reader-推荐使用,把网站改成暗黑主题,少数网站表现不好 uBlock Origin-推荐使用去广告 sourcegraph-推荐使用浏览器享受ide级别待遇 savetopdf-自动把网页转化为pdf es-client-elasticsearch客户端 Elasticvue-elasticsearch客户端 autocopy-自动复制选中内容 探索者小舒\u0026ndash;一键切换多个搜索引擎 Vue.js devtools-vue.js开发助手 jsonview-在浏览器中查看JSON 文件 Postwoman中文版-优秀Api测试插件 monknow新标签页,美观且允许高度自定义的新标签页扩展插件 chrome://flags/#enable-force-dark 自带暗黑模式 开发者模式-禁止网页跳转自动清除日志\n禁止页面跳过自动清除log lighthouse-chrome出品网站优化建议报告,dev-tools自带,方便又快捷\nfirefox开发者专用版,获取最新的开发者工具,帮助调试很多问题\nMDN-前端开发必备\nMDN-Mozilla开发者社区(MDN)是一个完整的学习平台 临时加载的脚本扩展,必须用cmd+shift+j调出浏览器控制台,设置\u0026quot;显示消息内容\u0026quot;,才能看到日志, PWA(Progressive Web App)-渐进式Web应用,利用缓存+在线网站构建本地应用 WebDriver是远程控制接口,可以对用户代理进行控制。它提供了一个平台和语言中性线协议,作为进程外程序远程指导web浏览器行为的方法.\n有空实现插件\n浏览器扩展 类似go search,python search 浏览器扩展 把github有关hg项目生成pdf dial,类似monknow 批量html转化成pdf "
},
{
"uri": "/flutter/",
"title": "flutter",
"tags": [],
"description": "",
"content": "中文官网 常用命令 # 检查环境 flutter doctor # 创建新工程 flutter create xxx # 调试运行 flutter run # 生成apk,默认release,上线应用市场需要签名,个人使用可以直接生成 flutter build apk # 插上数据线,连上手机,手机打开调试选项,直接安装 flutter install # 生成不同的ios应用,默认生成apple store,否则就指定用途 # 没有订阅会费,无法生成上架及ad-hoc,只能生成 development flutter build ipa --export-method ad-hoc、--export-method development 和 --export-method enterprise。 flutter build ipa --export-method development # 应用程序支持的最低 macOS 版本。Flutter 支持 macOS 10.11 及更高版本。Deployment Target(部署目标)需要注意. flutter build macos # 出现类似下面提示,可能是xcode版本或m1芯片造成,仍然可以正常打包 # --- xcodebuild: WARNING: Using the first of multiple matching destinations: # { platform:macOS, arch:arm64, id:xxxxx } # { platform:macOS, arch:x86_64, id:xxxx } # cd project/build/web # python3 -m http.server 8000 flutter build web # linux仅限linux主机支持 flutter build linux # windows仅限windows主机支持 flutter build windows 中国特定的环境变量,否则doctor失败 vim .zshrc vim .bashrc export CHROME_EXECUTABLE=/Applications/Chromium.app/Contents/MacOS/Chromium export PUB_HOSTED_URL=https://pub.flutter-io.cn export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn 本地跑起flutter官网 cd git-code/github/flutter-website # make up,如果不能,就先启动docker ./local.sh 知名扩展库 samples-flutter官方示例\nFair-界面动态化\nbruno-组件开源\nAppFlowy-开源笔记\nBundle和apk区别 Bundle是google推出一种文件格式,帮助下载时动态产生apk,以节省不必要的浪费.Google Play就是基于对aab文件处理,将App Bundle在多个维度进行拆分,在资源维度,ABI维度和Language维度进行了拆分,你只要按需组装你的Apk然后安装即可。如果你的手机是一个x86,xhdpi的手机,你在google play应用市场下载apk时,gogle play会获取手机的信息,然后根据App Bundle会帮你拼装好一个apk,这个apk的资源只有xhdpi的,而且so库只有x86,其他无关的都会剔除。从而减少了apk的大小。\nxcode无线调试真机(同局域内) 手机采用数据线连接上Xcode,打开Xcode菜单:Windows-\u0026gt;Device and Simulators。找到连接上的设备,把Connect via network选项打勾.\n之后Xcode将会转一会圈圈,耐心等待一会就成功了,此时拔掉数据线,可以看到左侧的设备连接列表上手机仍在列表中\n运行我们的项目,在设备列表中不出意外会看到我们的无线连接的手机。选择手机后运行\n不出意外的话,此时是跑不起来的。还需要最后一步,回到刚刚的设备列表中,选中手机右键,在出来的选项卡中选择一个Connect via IP Address项。选择之后输入手机的局域网ip地址。\n完成后可以看到在连接的手机右边有一个地球连接标志.\n以后项目运行,在下拉列表如果手机在局域网中也会有这个标志\n最后一步,选择后直接运行,不出意外的话,项目无需数据线就跑起来了\n此方法是支持无线调试的,连一次以后就不需要数据线了了\n苹果帐户添加设备uuid 打开https://developer.apple.com/ 登录你的苹果开发者账号,交过钱才能看到界面\n登进去之后点击Certificates, Identifiers \u0026amp; Profiles\n左侧点击Devices,可以看到现在账号里面注册的设备,再点击+号新增设备\n填写设备的名字(这个自己随便写就好了,方便你知道是谁的什么设备就行)还有设备的UDID,完成后点击Continue\n然后会让你再次确认信息,看你填写是否正确,下面显示的是该账号最多可以添加的测试设备数目和剩余可添加设备的数目。信息无误,点击Register下一步。再点击done完成注册,跳转回Devices页面,就可以看到我们新添加的设备了。如果是做app开发,需要重新打包之后,新设备才能进行测试\n平时打adhoc,不用打store包\niphone6 plus的uuid 0da336454935d7d38373cbd54a403cad888ba845\nxcode查看uuid iphone数据线连接MAC\n打开Xcode\n点击Window\u0026mdash;-\u0026gt;Devices and Simulators\u0026mdash;\u0026gt;在右侧可查看到identifier\nidentifier即为我们获取到的iPhone 的UDID\n总结 xcode真机调试\nxcode真机安装ipa\n"
},
{
"uri": "/golang/freetype/",
"title": "freetype",
"tags": [],
"description": "",
"content": "package main import ( \u0026#34;fmt\u0026#34; \u0026#34;image\u0026#34; \u0026#34;image/draw\u0026#34; \u0026#34;image/png\u0026#34; \u0026#34;os\u0026#34; \u0026#34;github.com/golang/freetype\u0026#34; ) func DrawText(text string) { data, err := ioutil.ReadFile(\u0026#34;/System/Library/Fonts/STHeiti Medium.ttc\u0026#34;) if err != nil { panic(err) } f, err := freetype.ParseFont(data) if err != nil { panic(err) } dst := image.NewRGBA(image.Rect(0, 0, 800, 600)) draw.Draw(dst, dst.Bounds(), image.White, image.Point{}, draw.Src) c := freetype.NewContext() c.SetDst(dst) c.SetClip(dst.Bounds()) c.SetSrc(image.Black) c.SetFont(f) fontSize := float64(50) // 字体越大, 显示越大 c.SetFontSize(fontSize) // Pt是控制起点,Pt{x,y},x表示左起点,y表示下起点,y-fontSize才是上起点 _, err = c.DrawString(text, freetype.Pt(0, int(fontSize))) if err != nil { panic(err) } pngFile, err := os.Create(\u0026#34;draw.png\u0026#34;) if err != nil { panic(err) } defer pngFile.Close() err = png.Encode(pngFile, dst) if err != nil { panic(err) } } func main() { DrawText(\u0026#34;中国人golang语言教程ABC122\u0026#34;) } "
},
{
"uri": "/golang/gin/",
"title": "gin",
"tags": [],
"description": "",
"content": "context中断原理 const abortIndex int8 = math.MaxInt8 / 2 // Abort prevents pending handlers from being called. Note that this will not stop the current handler. // Let\u0026#39;s say you have an authorization middleware that validates that the current request is authorized. // If the authorization fails (ex: the password does not match), call Abort to ensure the remaining handlers // for this request are not called. func (c *Context) Abort() { // c.index赋值很大值,从导致下次Next都不执行,达到阻断执行链目的 c.index = abortIndex } // Next should be used only inside middleware. // It executes the pending handlers in the chain inside the calling handler. // See example in GitHub. func (c *Context) Next() { c.index++ for c.index \u0026lt; int8(len(c.handlers)) { c.handlers[c.index](c) c.index++ } } memcache中间件 import ( \u0026#34;bytes\u0026#34; \u0026#34;net/http\u0026#34; \u0026#34;sync\u0026#34; \u0026#34;github.com/bradfitz/gomemcache/memcache\u0026#34; \u0026#34;github.com/gin-gonic/gin\u0026#34; ) var memcacheClientMux sync.Mutex var memcacheClient *memcache.Client // TODO,要不要带上http头部,例如:数据类型html/json/js,Date,Cache-control等等 type middleResp struct { // 匿名包括,变相继承 gin.ResponseWriter isOK bool key string expiration int32 // 如果匿名包括,变相继承会和ResponseWriter冲突,导致接口重复写 b bytes.Buffer } var StoreErrHandler func(error) func (mr *middleResp) writeStore() { if mr.b.Len() \u0026gt; 0 { err := memcacheClient.Set(\u0026amp;memcache.Item{ Key: mr.key, Flags: 0, Expiration: mr.expiration, Value: mr.b.Bytes(), }) if StoreErrHandler != nil { StoreErrHandler(err) } } } func (mr *middleResp) Write(body []byte) (int, error) { if mr.isOK \u0026amp;\u0026amp; memcacheClient != nil { _, err := mr.b.Write(body) if StoreErrHandler != nil { StoreErrHandler(err) } } return mr.ResponseWriter.Write(body) } func (mr *middleResp) WriteHeader(statusCode int) { mr.isOK = statusCode == http.StatusOK mr.ResponseWriter.WriteHeader(statusCode) } // Writes the string into the response body. func (mr *middleResp) WriteString(s string) (int, error) { return mr.ResponseWriter.WriteString(s) } func MemcacheStore(server string, expireSecond int32) gin.HandlerFunc { return MemcacheWrap(server, expireSecond, func(c *gin.Context) { c.Next() }) } func MemcacheWrap(server string, expireSecond int32, handler gin.HandlerFunc) gin.HandlerFunc { memcacheClientMux.Lock() defer memcacheClientMux.Unlock() if memcacheClient == nil { memcacheClient = memcache.New(server) } return func(c *gin.Context) { mr := \u0026amp;middleResp{ ResponseWriter: c.Writer, key: c.Request.RequestURI, expiration: expireSecond, } c.Writer = mr handler(c) mr.writeStore() } } main使用 import ( \u0026#34;fmt\u0026#34; \u0026#34;math/rand\u0026#34; \u0026#34;github.com/gin-gonic/gin\u0026#34; ) func main() { r := gin.Default() r.Use(gin.Logger()) r.GET(\u0026#34;/gin/wrap\u0026#34;, MemcacheWrap(\u0026#34;127.0.0.1:11211\u0026#34;, 100, wrap)) group := r.Group(\u0026#34;/gin/group\u0026#34;) group.Use(MemcacheStore(\u0026#34;127.0.0.1:11211\u0026#34;, 100)) group.GET(\u0026#34;/ping\u0026#34;, func(c *gin.Context) { c.JSON(200, gin.H{ \u0026#34;message\u0026#34;: \u0026#34;pong\u0026#34;, }) }) group.GET(\u0026#34;/gin\u0026#34;, func(c *gin.Context) { c.Data(200, \u0026#34;text/html\u0026#34;, []byte(fmt.Sprintf(\u0026#34;\u0026lt;H1\u0026gt;gin,%v\u0026lt;/H1\u0026gt;\u0026#34;, rand.Int())), ) }) r.Run(\u0026#34;0.0.0.0:5050\u0026#34;) } func wrap(c *gin.Context) { c.Data(200, \u0026#34;text/html\u0026#34;, []byte(fmt.Sprintf(\u0026#34;\u0026lt;H1\u0026gt;warp,%v\u0026lt;/H1\u0026gt;\u0026#34;, rand.Int())), ) } "
},
{
"uri": "/git/",
"title": "git",
"tags": [],
"description": "",
"content": "优秀文档 [git-scm]https://git-scm.com/book/zh/) 文件状态变迁图 flowchart LR subgraph WorkDirectory ut(Untracked) um(Unmodified)--编辑修改--\u003emd(Modified) end subgraph Staged s(Staged/Index) end subgraph Repo r(Commit对象) end WorkDirectory --add--\u003e Staged Staged --restore或checkout--\u003e WorkDirectory Staged --commit--\u003e Repo Repo --restore或reset或checkout--\u003e Staged sequenceDiagram actor ut as Untracked actor um as Unmodified actor m as Modified actor s as Staged/Index actor r as Repo opt 未跟踪新文件 ut-\u003e\u003es: add 跟踪 ut--\u003e\u003eum: 自动转为 r--\u003e\u003es: 放弃跟踪 restore --staged或rm --cached um--\u003e\u003eut: 放弃跟踪后自动转为 end opt 已跟踪 opt 已跟踪编辑 um-\u003e\u003em: 编辑 s--\u003e\u003eum: 放弃编辑 restore或checkout end opt 提交到stage/index m-\u003e\u003es: add r--\u003e\u003es: 放弃add restore --staged或reset end r--\u003e\u003eum: 放弃add和编辑 restore --staged --worktree或checkout head end opt 提交repo s-\u003e\u003er: commit r--\u003e\u003es: 放弃commit restore --source=HEAD~1 --staged或reset head~1 end r--\u003e\u003eum: 放弃commit和add和编辑 restore --source=HEAD~1 --staged --worktree或checkout head~1或reset --hard head~1 命令介绍 git rm, 删除WorkDictory,Staged/Index的文件\n命令快照 git rm [--cached] \u0026lt;pathspec\u0026gt;... 带上\u0026ndash;cached,则只删除Staged/Index,否则WorkDictory也删除 restore,从指定源恢复\n命令快照 git restore [\u0026lt;options\u0026gt;] [--source=\u0026lt;tree\u0026gt;] [--staged] [--worktree] [--] \u0026lt;pathspec\u0026gt;... 没有带上\u0026ndash;staged,则直接从Staged/Index恢复到WorkDictory 带上\u0026ndash;staged,则从repo(head或者source指定commit或tag)恢复到Staged/Index.如果同时要恢复WorkDictory,则带上\u0026ndash;worktree \u0026ndash;source默认值为head 命令是试验性的,行为可能会改变.THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE. reset,设置head,Reset current HEAD to the specified state\n命令快照-格式1 git reset [-q] [\u0026lt;tree-ish\u0026gt;] [--] \u0026lt;pathspec\u0026gt; 从指定的tree-ish恢复到staged/index,tree-ish不指定就采用head\n命令快照-格式2\ngit reset [\u0026lt;mode\u0026gt;] [\u0026lt;commit\u0026gt;] This form resets the current branch head to \u0026lt;commit\u0026gt; and possibly updates the index (resetting it to the tree of \u0026lt;commit\u0026gt;) and the working tree depending on \u0026lt;mode\u0026gt;. If \u0026lt;mode\u0026gt; is omitted, defaults to --mixed. The \u0026lt;mode\u0026gt; must be one of the following: 把head指向tree-ish mode不同值不同含义 \u0026ndash;soft,仅改动head \u0026ndash;mixed(默认值),改动head并且staged/index恢复为指定tree-ish里面,workdictory不改 \u0026ndash;herd,改动head并且staged/index,workdictory恢复为指定tree-ish里面 checkout,切换分支或恢复出指定文件\n命令快照-格式1 git checkout [-f|--ours|--theirs|-m|--conflict=\u0026lt;style\u0026gt;] [\u0026lt;tree-ish\u0026gt;] [--] \u0026lt;pathspec\u0026gt; 没有带上tree-ish,则直接从Staged/Index恢复到WorkDictory\n带上tree-ish,则从repo(tree-ish)恢复到Staged/Index和WorkDictory\ntree-ish 通常是head,commit值或tag之类\n命令快照-格式2\ngit checkout [-q] [-f] [-m] [[-b|-B|--orphan] \u0026lt;new_branch\u0026gt;] 没有带上-b,则直接切换指定分支,分支必须存在\n带上-b,则创建新分支,并且立即切换过去\n命令快照-格式3\n#从远程仓库/分支,创建本地分支,分支名同远程分支一样,两者建立跟踪关系 #切换到新分支,简化操作 git checkout --track remoteRepo/repoBranch revert返祖,产生新的提交commit来返回过去的特定提交\n命令快照 git revert [--[no-]edit] [-n] [-m parent-number] [-s] [-S[\u0026lt;keyid\u0026gt;]] \u0026lt;commit\u0026gt; git rever -m 1 head flowchart LR m1(commitXXXX) --commit--\u003e m2(commitYYYY) m2 --commit--\u003e m3(commitZZZZ) m3 --rever -m 1 head--\u003e m4(commitNNNN,但内容和commitYYYY一样) 标签\n#列出标签 git tag #查看指定标签 git show vxxx #打轻量标签 git tag v1.0 #打附注标签 git tag -a v2.0 -m \u0026#34;附加信息\u0026#34; #把标签vxxx推送到远程 git push origin vxxx commit对象 flowchart LR subgraph commitXXXX direction TB cx(CommitXXXX)--包含--\u003etx(Tree对象) tx--包含--\u003ebxa(Blob对象A) tx--包含--\u003ebxb(Blob对象b) tx--包含--\u003ebxc(Blob对象c) end subgraph commitYYYY direction TB cy(commitYYYY)--包含--\u003ety(Tree对象) ty--包含--\u003eby1(Blob对象1) ty--包含--\u003eby2(Blob对象2) end subgraph commitZZZZ direction TB cz(commitZZZZ)--包含--\u003etz(Tree对象) tz--包含--\u003ebzl(Blob对象l) tz--包含--\u003ebzm(Blob对象m) tz--包含--\u003ebzn(Blob对象n) tz--包含--\u003ebzo(Blob对象o) end commitXXXX --父对象--\u003e commitYYYY commitYYYY --父对象--\u003e commitZZZZ 分支\n#列出分支 git branch #查看分支详情 git branch -vv #创建分支issue100 git branch issue100 #跳到分支issue100 git checkout issue100 #创建hotfix并且立即切过去 git checkout -b hotfix #删除分支issue100 git branch -d issue100 #指定分支的跟踪远程分支 git branch --set-upstream-to=remote/branch branch #基于远程分支创建新分支并设置跟踪关系 git checkout --trace -b feature origin/feature #把hotfix分支合并到当前分支里 git merge hotfix # 合并没有历史交并的分支 git merge gitee master --allow-unrelated-histories #如果合并冲突,则编辑修改冲突文件,再提交 git commit -am \u0026#34;人工修改冲突\u0026#34; #变基是改变-指定分支(不指出则采用当前分支)的起点,并且起点后的提交重播一次 #以hotfix分支为起点,本分支已有提交重播一次,达到合并目的 git rebase hotfix #如果重播冲突,则编辑修改冲突文件,再提交 git commit -am \u0026#34;人工修改冲突\u0026#34; #解决冲突后提交,再继续完成变基操作 git rebase --continue rebase变基原则\n只对尚未推送或分享给别人的本地修改执行变基操作清理历史. 从不对已推送至别处的提交执行变基操作. 合并提交\ngit commit -am \u0026#34;first\u0026#34; # 编辑修改... git commit -am \u0026#34;second\u0026#34; # 编辑修改... git commit -am \u0026#34;three\u0026#34; # 交互式合并最近三个提交,如下图所示 # 默认从上到下,从旧到新列出来,可以编辑顺序 # 合并时从上到下执行,第一个一般是pack(基础),其他的为s(合并到基础去,pack改为s) # 退出保存后,会继续编辑合并信息. git rebase -i head~3 git commit git branch dev git checkout dev git commit git commit git checkout master git commit git commit git commit git merge dev gitGraph: options { \"nodeSpacing\": 100, \"nodeRadius\": 10 } end commit branch dev checkout dev commit commit checkout master commit commit commit merge dev 远程仓库 flowchart LR subgraph 本地仓库前 lm(master) ld(dev) end subgraph 远程仓库 rm(master) rd(dev) rh(hotfix) end subgraph 本地仓库后 am(master) ad(dev) arm(origin/master) ard(origin/dev) arh(origin/hotfix) end 本地仓库前 --remote add orgin--\u003e 远程仓库 本地仓库前 --fetch origin--\u003e 本地仓库后 #添加远程库 git remote add name url # 如果远程库有意外提交,可以强行合并进来,再推上去 git pull origin master --allow-unrelated-histories #拉取远程库内容 git fetch name #查看远程分支日志 git log name/branch #创建本地分支branch并且跟踪到远程分支 git checkout --track name/branch #推送到远程 git push #删除远程分支 git push name -d branch #查看本地分支与远程分支设置 git branch -vv 集中式工作流程 sequenceDiagram actor da as 开发者A actor r as 仓库 actor db as 开发者B da-\u003e\u003er: clone db-\u003e\u003er: clone da-\u003e\u003eda: commit db-\u003e\u003edb: commit da-\u003e\u003er: push db-\u003e\u003er: pull db-\u003e\u003er: push pull-request工作流程,同一个仓库用不同分支替代仓库,类似流程 sequenceDiagram actor da as 开发者A actor dar as 开发者A仓库 actor r as 仓库 actor rw as 仓库维护者 actor db as 开发者B actor dbr as 开发者B仓库 opt 开发者A流程 da-\u003e\u003er: fork r--\u003e\u003edar: 自动创建 da-\u003e\u003edar: clone da-\u003e\u003eda: commit da--\u003e\u003edar: push dar--\u003e\u003er: pull requestA dar--\u003e\u003erw: 通知 end opt 开发者B流程 db-\u003e\u003er: fork r--\u003e\u003edbr: 自动创建 db-\u003e\u003edbr: clone db-\u003e\u003edb: commit db--\u003e\u003edbr: push dbr--\u003e\u003er: pull requestB dbr--\u003e\u003erw: 通知 end opt 仓库维护者流程 rw-\u003e\u003er: merge pull requestA rw-\u003e\u003er: merge pull requestB end 储存栈 #把workdirectory已跟踪修改+staged/index储存到一个栈上, git stash #可以在任何一个干净状态恢复出来,不一定需要原来保存的分支里 #不带上--index,则只恢复workdirectory已跟踪修改, #带上--index,则staged/index也一起恢复 git stash apply [--index] #apply可以多次重复 #删除就用drop git stash drop 杂项 #配置本项目用户 git config user.name \u0026#39;username\u0026#39; git config user.email \u0026#39;[email protected]\u0026#39; # 配置默认的分支名称 git config --global init.defaultBranch master #修改最近提交的author #amend纠正最近一次提交 #此次也会提交stage/index内容,如果stage/index没有修改,则直修改提交信息 git commit --amend --reset-author # 查看最近3次提交文件变化情况 git log -3 --stat #查看指定文件提交记录 git log -p filename # 查看该文件的相关commit git log -- filename # 查看指定提交特定文件的变化 git show commit_id filename # 查看指定提交的变化 git show commit_id #比较两次提交之间指定目录的区别 git diff 26be34b 934d76fd flow/proto_file # 有时候git status显示有变化,但是git diff没有,可能是文件换行符及文件权限属性变化了 git diff --cached filename #当前指定提交commit值 rem \u0026#39;git rev-parse --short HEAD\u0026#39; #记录本项目git版本,获取当前git版本值 Cgithash=`git rev-parse --short HEAD` #获取当前时间 Ctime=`date \u0026#39;+%Y-%m-%d_%H:%M:%S\u0026#39;` # 强制退回指定commit #fa2850...是commit的hash值 git reset --hard fa285014d635190e74cd40fc798ce26243766a09 #带用户名及密码的git clone git clone http://uer:[email protected] # 本地修改不提交到远程仓库 git update-index --skip-worktree filePath # post-receive钩子 # git pull引入$GIT_DIR变量,因此需要取消变量 unset $(git rev-parse --local-env-vars); git pull # 查看特定提交在哪里分支 git branch --contains xxxx -all # 创建一个空分支,没有任何父节点 git checkout --orphan newBranch git rm -rf . # 如何没有任何文件提交,看不到新建的分支 git commit -am \u0026#34;newBranch\u0026#34; 积累 官网\nGit gc一般情况不用手动,gc主要把无用的内部对象回收,一般都自动处理\nGit钩子都被存储在 Git 目录下的 hooks 子目录中.\n.git目录内容 git引用 查看项目本地仓库,远程仓库,标签等\ntree .git/refs Git 可以使用四种不同的协议来传输资料:\n本地协议(Local) #本机clone,尽量采用不带file://前缀,加快速度 git clone /srv/git/project.git git clone file:///srv/git/project.git HTTP 协议,现在git一般采用智能 HTTP 协议 git clone https://example.com/gitproject.git SSH(Secure Shell)协议 git clone ssh://[user@]server/project.git git clone [user@]server:project.git Git 协议 Git里的一个特殊的守护进程,它监听在一个特定的端口(9418) 速度最快的 缺乏授权机制 git:// 利用post-receive钩子自动更新\n#!/usr/bin/env bash # post-receive脚本代码 cd ~ target=xxx # 简单粗暴,删除旧目录 if [ -d ${target} ]; then rm -rf ${target} fi # 重新建立,从git代码库目录 git clone gogs-repositories/yyy/${target}.git # 杀死进程 pkill ${target} cd ${target} # 后台运行进程 nohup ./${target} \u0026gt;${target}.nohup 2\u0026gt;\u0026amp;1 \u0026amp; push碰到HTTP 413\n问题表现 Git push error: error: RPC failed; HTTP 413 curl 22 the requested URL returned error: 413 解决办法 # 增加最大http长度 git config –global http.postBuffer 524288000 location / { ... # 如果有nginx转发 client_max_body_size 200M; ... } 多项目-一个项目(采用git管理)使用另一个项目(采用git管理) Git Submodule\n添加子目录\n# 默认在目录下建立repo子目录,并且克隆仓库,并且创建.gitmodules git submodule add https://xxx/repo.git # 提交到仓库 git commit -am \u0026#34;submodule\u0026#34; # 如果子项目有更新,直接取更新 git submodule update --remote # 然后更新父目录,子项目引用到更新后的 git commit -am \u0026#34;更新submodule\u0026#34; #可以直接在子目录修改提交,和正常git操作一样 其他人使用\n# 一次性克隆项目及子项目 git clone --recursive https://xxx/repo.git # 或者先克隆项目 git clone https://xxx.git # 手动更新子项目 git submodule init git submodule update --remote #可以直接在子目录修改提交,和正常git操作一样 子项目.git目录储存到父项目的.git/modules目录 用引用方式,显式操作\nGit Subtree\n添加子目录,建立与git项目的关联\n#-f在添加远程仓库之后,立即执行fetch git remote add -f \u0026lt;子仓库名\u0026gt; \u0026lt;子仓库地址\u0026gt; #–squash意思是把subtree的改动合并成一次commit,不用拉取子项目完整的历史记录。 #–prefix之后的=等号也可以用空格。 git subtree add --prefix=\u0026lt;子目录名\u0026gt; \u0026lt;子仓库名\u0026gt; \u0026lt;分支\u0026gt; --squash 从远程仓库更新子目录\ngit fetch \u0026lt;远程仓库名\u0026gt; \u0026lt;分支\u0026gt; git subtree pull --prefix=\u0026lt;子目录名\u0026gt; \u0026lt;远程分支\u0026gt; \u0026lt;分支\u0026gt; --squash 从子目录push到远程仓库(确认你有写权限)\ngit subtree push --prefix=\u0026lt;子目录名\u0026gt; \u0026lt;远程分支名\u0026gt; 分支 用复制方式,隐式操作\nGitSlave\n清除大文件 采用工具\n清理仓库大文件需要修改仓库的提交历史,git-filter-repo 是 Git 官方社区推荐的修改仓库提交历史的工具,本文介绍使用 git-filter-repo 来清理仓库大文件的方法。 看他\npip3 install git-filter-repo 手动执行\n# 完全清除git中大文件提交 # 查看大文件 # 使用verify-pack命令查看, pack包里面的最大的10个文件对应的hash值 # 根据rev-list命令来查看, 最大的文件的文件名是什么 git rev-list --objects --all | grep \u0026#34;$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10 | awk \u0026#39;{print$1}\u0026#39;)\u0026#34; # 删除大文件 git filter-branch --force --index-filter \u0026#34;git rm -rf --cached --ignore-unmatch linux_x86_64/zinc_upx\u0026#34; --prune-empty --tag-name-filter cat -- --all # 回收空间,清理本地仓库不可达对象; git for-each-ref --format=\u0026#39;delete %(refname)\u0026#39; refs/original | git update-ref --stdin rm -rf .git/refs/original/ rm -rf .git/logs/ git reflog expire --expire=now --all git gc --prune=now git gc --aggressive --prune=now # 强制推到远程 git push origin --force --all # git push origin –-force --tag git remote prune origin # !!清理完之后,每个人一定要删掉之前拉取的项目, 重新从git上拉项目。不要使用之前的项目了!否则会不降反升。 清除未跟踪文件 # 清除文件 git clean -f # 连目录也一起清除文件 git clean -fd "
},
{
"uri": "/other/github/",
"title": "github",
"tags": [],
"description": "",
"content": "重要提示 替代品-gitlab 中文社区-github ossinsight- api文档-github 解决访问超慢 ip address.com查域名 修改/etc/hosts\n140.82.113.21 collector.Github.com 140.82.113.5 api.github.com 140.82.114.4 github.com 140.82.113.4 github.com 185.199.108.154 github.githubassets.com 185.199.109.154 github.githubassets.com 185.199.110.154 github.githubassets.com 185.199.111.154 github.githubassets.com 185.199.110.153 assets-cdn.github.com 185.199.111.153 assets-cdn.github.com 185.199.108.153 assets-cdn.github.com 199.232.69.194 github.global.ssl.fastly.net 原因是国内dns解析相应域名都是到新加坡,有时候访问不了\nFastGithubgithub加速神器\nosx-arm64版本会直接被杀死,改用osx-x86\n[1] 9226 killed ./fastgithub # 丢掉烦人的输出,并且后台运行 ./fastgithub \u0026gt; /dev/null \u0026amp; godoc -http=:6060 \u0026amp; MacOSx配置\n最新版firefox替换证书, 证书-查看证书-颁发机构-导入cer证书,否则报错\n设置系统自动代理为http://127.0.0.1:38457,或手动代理http/https为127.0.0.1:38457\npages服务 User/Organization Pages 个人或公司站点\n创建username.github.io仓库 仓库设置自定义域名,项目下面会自动增加CNAME文件 域名解析增加相应的CNAME记录 Project Pages 项目站点\ngh-pages分支用于构建和发布; 如果user/org pages使用了独立域名,那么托管在账户下的所有project pages将使用相同的域名进行重定向,除非project pages使用了自己的独立域名; 如果没有使用独立域名,project pages将通过子路径的形式提供服务http://username.github.com/projectname; 自定义github主页 新建一个同名仓库\n官方提示:\u0026hellip;. is a special repository. Its README.md will appear on your public profile!\n编辑该仓库的 README.md 文件\n官方工具 GitHub Desktop GitHub CLI 名词 Sponsor:打赏\nWatch:如有更新,通知提醒。\nFork:分支一份到你的仓库。\nCode:默认页面,通常会有一个 README.md 文件,用于介绍该项目。\nPull requests:请求代码合并,如果你想为项目贡献代码,可以在这里提交。\nActions:工作流。\n大家知道,持续集成由很多操作组成,比如抓取代码、运行测试、登录远程服务器,发布到第三方服务等等。GitHub 把这些操作就称为 actions。 很多操作在不同项目里面是类似的,完全可以共享。GitHub 注意到了这一点,想出了一个很妙的点子,允许开发者把每个操作写成独立的脚本文件,存放到代码仓库,使得其他开发者可以引用。 如果你需要某个 action,不必自己写复杂的脚本,直接引用他人写好的 action 即可,整个持续集成过程,就变成了一个 actions 的组合。这就是 GitHub Actions 最特别的地方。 GitHub 会监控到,然后分配一台虚拟机先将你的项目 checkout 过去,然后按照你指定的 step 顺序执行定义好的 action\nProjects:项目管理\nSecurity:安全评估\nWiki:说明文档\nInsights:数据统计\ncodespaces 类似web IDE,省去环境配置环节,云端开发\n高级搜索 例如包括nginx的pdf书 nginx extension:pdf\n配套网站-Netlify 用最快的方法构建最快的网站 当使用 Github 将网站项目文件夹里的所有东西上传完毕之后,那么就可以打开 Netlify 给予它访问 Github 仓库的权限。 当 Netlify 读取完你的网站所属仓库时,会自动识别你所用的静态网页生成器的程序,然后只要点击部署并发布,你的网站就会在 Netlify 被构建并且被发布.\n能够托管服务,免费 CDN\n能够绑定自定义域名\n能够启用免费的TLS证书,启用HTTPS\n支持自动构建\n提供 Webhooks 和 API\n开源有趣项目-介绍\ngithub-中文社区\n多个帐号,多个ssh # ~/.ssh/config配置 Host github3 HostName github.com PreferredAuthentications publickey IdentityFile ~/.ssh/id_rsa Host github2 HostName github.com PreferredAuthentications publickey IdentityFile ~/.ssh/id_ecdsa # 修改远程地址 # [email protected]:xxx/yyy -\u0026gt; git@github3:xxx/yyy # [email protected]:xxx/yyy -\u0026gt; git@github2:xxx/yyy "
},
{
"uri": "/other/gitlab/",
"title": "gitlab",
"tags": [],
"description": "",
"content": "安装私有部署(内存最低2GB,机器配置越高越好,否则会有各种问题) # 下载安装docker curl -fsSL \u0026lt;https://get.docker.com\u0026gt; | bash -s docker --mirror Aliyun # 启动docker systemctl start docker # 创建gitlab home mkdir /srv/gitlab # 导出环境变量 vim .bash_profile export GITLAB_HOME=/srv/gitlab # docker跑起来,采用社区版,自带常见服务足够了 docker run --detach \\ --hostname gitlab.example.com \\ --publish 443:443 --publish 80:80 --publish 8090:22 \\ --name gitlab \\ --restart always \\ --volume $GITLAB_HOME/config:/etc/gitlab \\ --volume $GITLAB_HOME/logs:/var/log/gitlab \\ --volume $GITLAB_HOME/data:/var/opt/gitlab \\ --shm-size 256m \\ registry.gitlab.cn/omnibus/gitlab-jh:latest # 初始化过程可能需要很长时间。 您可以通过以下方式跟踪此过程,查看日志 docker logs -f gitlab # 获取默认初始化密码,用户名是root docker exec -it gitlab grep \u0026#39;Password:\u0026#39; /etc/gitlab/initial_root_password 官方安装说明\n# 安装sourcegraph docker run --detach \\ --publish 8091:7080 \\ --publish 127.0.0.1:3370:3370 \\ --rm --volume ~/.sourcegraph/config:/etc/sourcegraph \\ --volume ~/.sourcegraph/data:/var/opt/sourcegraph sourcegraph/server:3.40.0 "
},
{
"uri": "/golang/go-git/",
"title": "go-git",
"tags": [],
"description": "",
"content": " package main import( \u0026#34;fmt\u0026#34; \u0026#34;github.com/go-git/go-git/v5\u0026#34; \u0026#34;github.com/go-git/go-git/v5/plumbing/object\u0026#34; ) func gitWork() { r, err := git.PlainOpen(\u0026#34;../wubei/wubei\u0026#34;) if err != nil { fmt.Println(err) return } fmt.Println(\u0026#34;r\u0026#34;, r) // ... retrieves the branch pointed by HEAD ref, err := r.Head() if err != nil { fmt.Println(err) return } fmt.Println(\u0026#34;ref\u0026#34;, ref) // ... retrieves the commit history cIter, err := r.Log(\u0026amp;git.LogOptions{From: ref.Hash()}) if err != nil { fmt.Println(err) return } var cCount int err = cIter.ForEach(func(c *object.Commit) error { cCount++ fmt.Println(\u0026#34;Author\u0026#34;, c.Author) fmt.Println(\u0026#34;Message\u0026#34;, c.Message) return nil }) if err != nil { fmt.Println(err) return } fmt.Println(\u0026#34;cCount\u0026#34;, cCount) } "
},
{
"uri": "/golang/",
"title": "golang",
"tags": [],
"description": "",
"content": "官网 Go Search Extension浏览器扩展, 地址栏输入go+空格启用 golang.org国内经常访问不了 通过go bulid -tags 实现编译控制 内置数据类型定义在runtime包,如下图所示 吐槽一下 破坏注释不影响代码的传统,这类//go:注释,有特别含义,会影响代码作用,使用者非常容易误解 强制mod方式管理第三方模块 用代码库+版本解决依赖 带来重大著名库大量重复存在,GOPATH成垃圾桶 带来更多名词,增加心智负担,精力分散在语言之外过多 严重偏向开源开发模式,对闭源开发不友好 环境变量 # 安装到默认目录 rm -rf /usr/local/go \u0026amp;\u0026amp; tar -C /usr/local -xzf go1.19.linux-amd64.tar.gz # 导出环境变量 export PATH=$PATH:/usr/local/go/bin # 查看安装成功否 go version #列出环境变量 go env #GOPATH环境变量,如果没有手动设置,默认为$HOME/go GOPATH=$HOME/go #模块缓存是 go 命令存储下载模块文件的目录,默认是$GOPATH/pkg/mod. GOMODCACHE #清除mod cache,pkg目录里面全没了 go clean --modcache #Build Cache意思就是会把编译过程的中间结果cache下来,从而实现增量编译。 #Test cache,在内容没有变化的情况下,对于同样的参数的测试,会直接使用cache的测试结果 #cache默认的存储路径是操作系统所确定的用户缓存目录,但是可以通过GOCACHE环境变量修改 GOCACHE #清除build cache go clean -cache #清除test cache go clean -testcache #GOPROXY(公共)修改为国内代理 #全球代理https://proxy.golang.com.cn(https://goproxy.io/) #阿里云 https://mirrors.aliyun.com/goproxy/ #七牛云 https://goproxy.cn #direct表示直接从包路径下载 go env -w GOPROXY=https://goproxy.cn,direct #GOPRIVATE设置私有库 #还可以设置不走 proxy 的私有仓库或组,多个用逗号相隔(可选) #允许通配符 go env -w GOPRIVATE=git.mycompany.com,github.com/my/private,*.example.com #GOVCS变量 #可以使用git下载带有 github.com 路径的模块;无法使用任何版本控制命令下载 evil.com上的路径 #使用 git 或 hg 下载所有其他路径(* 匹配所有内容)的模块。 GOVCS=github.com:git,evil.com:off,*:git|hg #GOSUMDB变量 #默认的GOSUMDB=sum.golang.org验证包的有效性,经常访问不了 go env -w GOSUMDB=off #使用国内代理 go env -w GOSUMDB=https://goproxy.cn/sumdb/sum.golang.org,sum.golang.org GOPROXY说明\nYou can set the variable to URLs for other module proxy servers, separating URLs with either a comma or a pipe. When you use a comma, Go tools will try the next URL in the list only if the current URL returns an HTTP 404 or 410. GOPROXY=\u0026#34;https://proxy.example.com,https://proxy2.example.com\u0026#34; When you use a pipe, Go tools will try the next URL in the list regardless of the HTTP error code. GOPROXY=\u0026#34;https://proxy.example.com|https://proxy2.example.com\u0026#34; GOPRIVATE说明\nThe GOPRIVATE or GONOPROXY environment variables may be set to lists of glob patterns matching module prefixes that are private and should not be requested from any proxy. GOVCS说明\n版本控制工具中的错误可能被恶意服务器利用来运行恶意代码 如果未设置环境变量GOVCS,或者不匹配,GOVCS的默认处理:允许 git 和 hg 用于公共模块,并且允许所有工具用于私有模块。 go mod命令指南 #最后结果都是写入go.mod文件 go mod init path go mod edit --replace modulepath=otherpath go mod edit --exclude modulepath #tidy整理依赖,增加没有添加或移除未引用等 go mod tidy #整检依赖是否正解 go mod verify 采用mod方式管理依赖,则没有gopath/src,改到gopath/mod go.sum不需要手工维护,也不要手工改动 所有的子目录里的依赖都组织在根目录的go.mod文件 replace指令场景 替换无法下载的包 替换本地自己的包 替换 fork 包 exclude显式的排除某个包的某个版本,例如某个版本有严重bug,如果其他包引用这个版本,就会自动跳过这个版本 文章介绍较直白 文章介绍retract指令 工作区-多模块 #最后结果都是写入go.work文件 Usage: go work \u0026lt;command\u0026gt; [arguments] The commands are: edit edit go.work from tools or scripts init initialize workspace file sync sync workspace build list to modules use add modules to workspace file workspace目录 go.work内容 #go work use ./hello #go work use ./example #./hello,./example是本地路径,不是example,hello的module名 go 1.18 use ( ./example ./hello ) hello/main.go内容 package main import ( \u0026#34;fmt\u0026#34; \u0026#34;golang.org/x/example/stringutil\u0026#34; ) func main() { fmt.Println(stringutil.ToUpper(\u0026#34;Hello\u0026#34;)) } hello/go.mod内容 module example.com/hello go 1.18 require golang.org/x/example v0.0.0-20220304235025-ad95e7f791d8 // indirect 在workspace目录下运行go run example.com/hello 不用改动go.mod,使得golang.org/x/example由本工作区的example替代 可实现多模块同时开发 相关工具go tools get/install下载包过程 // import \u0026#34;example.org/pkg/foo\u0026#34; // // will result in the following requests: // // https://example.org/pkg/foo?go-get=1 (preferred) // http://example.org/pkg/foo?go-get=1 (fallback, only with use of correctly set GOINSECURE) // // If that page contains the meta tag // // \u0026lt;meta name=\u0026#34;go-import\u0026#34; content=\u0026#34;example.org git https://code.org/r/p/exproj\u0026#34;\u0026gt; // // the go tool will verify that https://example.org/?go-get=1 contains the // same meta tag and then git clone https://code.org/r/p/exproj into // GOPATH/src/example.org. // go get/install当服务器支持多种协议优先使用https://, 然后git+ssh://. #包括godoc等工具 #./godoc -http :6060 go install golang.org/x/tools/...@latest. #浏览器本地文档,如果起启目录有go.mod会继续分析提供文档,但是增加启动时间 godoc -http :6060 #安装pprof,如果不在mod目录下运行,就指明@latest最近版本 go install github.com/google/pprof@latest #下载最新版本 go get example.com/theirmodule@vlatest #下载指定版本 go get example.com/[email protected] go get example.com/theirmodule@4cf76c2 go get example.com/theirmodule@bugfixes #移除指定版本模块 go get example.com/theirmodule@none #查看所有依赖模块的最新版本 go list -m -u all #查看指定模块的最新版本 go list -m -u example.com/theirmodule #升级后会将新的依赖版本更新到go.mod go get -u need-upgrade-package #升级所有依赖 go get -u go tool pprof go tool trace #获取当前git hash Cgithash=$(git rev-parse --short HEAD) #获取当前时间 Ctime=$(date \u0026#39;+%Y-%m-%d_%H:%M:%S\u0026#39;) # 交叉编译 # 禁止cgo # 设置编译目标平台 # 设置编译芯片体系 #-s: 去掉符号表; -w:去掉调试信息,不能gdb调试了; CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -o ${target} -ldflags \u0026#34;-s -w -X main.GitHash=${Cgithash} -X main.CompileTime=${Ctime}\u0026#34; main.go #获取程序更多信息(包括-ldflags参数设置) go version -m 二进制可执行文件 #新增inittrace指令, 用于init调试和启动时间的概要分析 GODEBUG=inittrace=1 go run main.go #简化代码 gofmt -s -w xxx.go 文章介绍pprof 文章介绍trace 创建protoc插件 golangci-lint,替代品lint-静态检查库 #快速安装,会自动下载依赖安装对应的go版本,如果系统安装有go,那么注意搜索PATH brew install golangci-lint #手动下载,选择最新及相应的平台,最新版本在go1.18有部分lint不支持,需要适时更新 https://github.com/golangci/golangci-lint/releases #较大规模项目,或第一次运行应该增加超时选择 #golangci-lint会采用缓存,如果环境变没有设置,则采用系统默认设置 golangci-lint run --timeout=1h #GolangCI-Lint looks for config files in the following paths from the current working directory: .golangci.yml .golangci.yaml .golangci.toml .golangci.json #这几个参数比较有用 skip-dirs: - src/external_libs - autogenerated_by_my_lib # Enables skipping of directories: # - vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ # Default: true skip-dirs-use-default: false # Which files to skip: they will be analyzed, but issues from them won\u0026#39;t be reported. # Default value is empty list, # but there is no need to include all autogenerated files, # we confidently recognize autogenerated files. # If it\u0026#39;s not please let us know. # \u0026#34;/\u0026#34; will be replaced by current OS file path separator to properly work on Windows. skip-files: - \u0026#34;.*\\\\.my\\\\.go$\u0026#34; - lib/bad.go 小米出品-Soar-sql优化改写 #手动下载,选择最新及相应的平台,老黄历版本啦! https://github.com/XiaoMi/soar/releases #源码安装,报gopath/pkg/mod/github.com/!xiao!mi/[email protected]/ast/tidb.go:24:2: ambiguous import: #解决办法:跳过此种方式,估计没有指到最新版本,没心情找原因 go install github.com/XiaoMi/soar/cmd/soar@latest #最原始办法 git clone https://github.com/XiaoMi/soar.git cd soar make #测试使用 echo \u0026#39;select * from film\u0026#39; | ./soar go generate命令 当运行go generate时,它将扫描与当前包相关的源代码文件,找出所有包含\u0026quot;//go:generate\u0026quot;的特殊注释\n提取并执行该特殊注释后面的命令,命令为可执行程序,形同shell下面执行\n该特殊注释必须在.go源码文件中。 每个源码文件可以包含多个generate特殊注释时。 显示运行go generate命令时,才会执行特殊注释后面的命令。 命令串行执行的,如果出错,就终止后面的执行。 特殊注释必须以\u0026quot;//go:generate\u0026quot;开头,双斜线后面没有空格。 应用\nyacc:从 .y 文件生成 .go 文件。 protobufs:从 protocol buffer 定义文件(.proto)生成 .pb.go 文件。 Unicode:从 UnicodeData.txt 生成 Unicode 表 go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages] 参数说明如下:\n-run 正则表达式匹配命令行,仅执行匹配的命令; -v 输出被处理的包名和源文件名; -n 显示不执行命令; -x 显示并执行命令; command 可以是在环境变量 PATH 中的任何命令。 核心语法 逃逸分析\n目标:减轻堆内存分配开销,减少gc压力,提高运行性能\n编译器会做逃逸分析(escape analysis),变量的作用域没有跑出函数范围,在栈上,反之在堆上。\n实践\n#输出分析结果 go build -gcflags \u0026#39;-m -l\u0026#39; main.go #反汇编查看,出现runtime.newobject,就发现逃逸行为 go tool compile -S main.go 结论\n常见逃逸\n在某个函数中new或字面量创建出的变量,将其指针作为函数返回值,则该变量一定发生逃逸(构造函数返回的指针变量一定逃逸);\n建议:调用方传入参,被调用方直接把结果存进去\n比如 read 函数的签名是 read([]byte),而不是 read() []byte,就是为了避免堆分配.\n被已经逃逸的变量引用的指针,一定发生逃逸;\n被指针类型的slice、map和chan引用的指针,一定发生逃逸,所以slice,map,chan尽管传值,不使用传指针,除非超大复制量;\n申请超大容量变量,栈空间是有限的\n作为fmt.printxxx参数,没事少用点\nmake,new,字面量初始化变量都一样要逃逸分析\n常见不逃逸\n指针被未发生逃逸的变量引用; 仅仅在函数内对变量做取址操作,而未将指针传出; 可能发生逃逸\n将指针作为入参传给别的函数;这里还是要看指针在被传入的函数中的处理过程,如果发生了上边的三种情况,则会逃逸;否则不会逃逸; 泛型\n类型参数:泛型的抽象数据类型。 TypeParameters = \u0026#34;[\u0026#34; TypeParamList [ \u0026#34;,\u0026#34; ] \u0026#34;]\u0026#34; . TypeParamList = TypeParamDecl { \u0026#34;,\u0026#34; TypeParamDecl } . TypeParamDecl = IdentifierList TypeConstraint . 类型约束:确保调用方能够满足接受方的程序诉求。 TypeConstraint = TypeElem . TypeElem = TypeTerm { \u0026#34;|\u0026#34; TypeTerm } . TypeTerm = Type | UnderlyingType . UnderlyingType = \u0026#34;~\u0026#34; Type . /* 内置comparable类型约束 comparable is an interface that is implemented by all comparable types (booleans, numbers, strings, pointers, channels, arrays of comparable types, structs whose fields are all comparable types). The comparable interface may only be used as a type parameter constraint, not as the type of a variable.*/ type comparable interface{ comparable } 类型推导:避免明确地写出一些或所有的类型参数。\n为保证GO1兼容性,标准库并没有引入泛型,试验性在golang.org/x/exp里\nGo 1.15 增加了一个新程序包,time/tzdata。该程序包允许将时区数据库嵌入程序中\nGo1.16 开始禁止 import 导入的模块以 . 开头,模块路径中也不允许出现任何非 ASCII 字符\nGo 1.16 新增的 embed 包支持资源嵌入\n//把资源文件打包到二进制文件中 import ( \u0026#34;fmt\u0026#34; //go1.16引入新的标准库 _ \u0026#34;embed\u0026#34; \u0026#34;runtime/debug\u0026#34; ) //golang特有编译器指示,类似//go:noinline,go:build //go:embed hello.txt var hello string func main() { //调试好帮手,打印出调用栈 debug.PrintStack() fmt.Println(\u0026#34;hello:\u0026#34;, hello) } 弃用 io/ioutil,已移至其他程序包 timer性能提升,defer的性能,几乎是零开销 合并结构体标签tag设置标识 type MyStruct struct { Field1 string `json:\u0026#34;field_1,omitempty\u0026#34; bson:\u0026#34;field_1,omitempty\u0026#34; xml:\u0026#34;field_1,omitempty\u0026#34; form:\u0026#34;field_1,omitempty\u0026#34; other:\u0026#34;value\u0026#34;` } // 就可以通过合并的 type MyStruct struct { Field1 string `json,bson,xml,form:\u0026#34;field_1,omitempty\u0026#34; other:\u0026#34;value\u0026#34;` } context 主要用来在 goroutine 之间传递上下文信息,包括:取消信号、超时时间、截止时间、k-v 等.这篇文章解释清楚.\n上游的信息共享给下游任务 上游可发送取消信号给所有下游任务,不会直接干涉和中断下游任务的执行,下游任务自行决定后续的处理操作. 下游任务自行取消不会影响上游任务 源码不理解? 字符串,只读的切片,写入操作都是通过拷贝实现的。\n// 原始,特别适合不要转义 var rawString = `\\n \\b \\s \\u` // 带转义 normalStr := \u0026#34;aabbcc\u0026#34; // 从string转[]byte,从[]byte转string,都是拷贝数据 // 而内存拷贝的性能损耗会随着字符串和 []byte 长度的增长而增长。 数字字面量,下划线只为美观 // 二进制110 var binary = 0b1_1_0 // 十进制712 var digit = 7_1_2 // 向下取整,div=3 var div = 7 / 2 数组 //明确指出 arr1 := [3]int{1, 2, 3} //编译器推定 arr2 := [...]int{1, 2, 3} /* 数组元素+数组大小相同才是同一类型,才能相等 */ 切片 //使用下标初始化切片不会拷贝原数组或者原切片中的数据,它只会创建一个指向原数组的切片结构体,所以修改新切片的数据也会修改原切片 arr[0:3] or slice[0:3] //最终转化为上面方式 slice := []int{1, 2, 3} //如果len/cap较小,最终转化为上面方式,否则运行时处理 slice := make([]int, 10) /* make([]type, len) 相当于 make([]type, len, len) b ;= a[low : high : max] b[0] = a[low] len(b) = high-low cap(b) = max - low a[low:high] 相当于 a[low : high : cap(a)] a[:high] 相当于 a[0:high] a[low:] 相当于 a[low:len(a)] a[:] 相当于 a[0:len(a)] */ map cap理论上都是无穷的,使用自动扩容 内置的map多协程操作不安全 sync.map是多协程安全 //len是0 firstMap := make(map[string]int) //len是0,10只是帮助初次cap大小 secMap := make(map[string]int, 10) //len是2, threeMap := map[string]int{ \u0026#34;one\u0026#34;: 1, \u0026#34;two\u0026#34;: 2, } // 一般建议这种访问,区别val是否有效 val, exist := threeMap[\u0026#34;one\u0026#34;] delete(threeMap, \u0026#34;two\u0026#34;) 函数\n参数的计算是从左到右\n参数是值传递,返回值也是值传递,影响深远 slice,make,chan底层实现struct中包括指针,从而实现引用效果\n接口\nruntime.iface带方法,runtime.eface不带方法,两种不同. type eface struct { _type *_type data unsafe.Pointer } type iface struct { tab *itab data unsafe.Pointer } type itab struct { inter *interfacetype _type*_type // 类型断言时使用,复制_type中hash hash uint32 ... fun [1]uintptr } type _type struct { ... ptrdata uintptr // 类型断言时使用 hash uint32 ... equal func(unsafe.Pointer, unsafe.Pointer) bool ... } 隐式实现,区别其他语言 接口本身为nil,和接口值为nil是两回事 直接调用OR动态派发?编译器优化会把动态派发改为直接调用,以减少性能的额外开销. type Person interface { Speak() } type Man struct { Voice string } func (m *Man) Speak() { fmt.Println(\u0026#34;Voice:\u0026#34;, m.Voice) } func main() { m := \u0026amp;Man{Voice: \u0026#34;firstMan\u0026#34;} var p Person = m //直接调用,类型转换是编译期完成 p.(*Man).Speak() //动态派发,比直接调用多取出data和fun两个动作 p.Speak() } gc\n暂停程序(Stop the world,STW),随着程序申请越来越多的内存,系统中的垃圾也逐渐增多;当程序的内存占用达到一定阈值时,整个应用程序就会全部暂停,垃圾收集器会扫描已经分配的所有对象并回收不再使用的内存空间,当这个过程结束后,用户程序才可以继续执行.\n垃圾收集可以分成清除终止、标记、标记终止和清除\n用户程序,分配器,gc收集器,head关系图 sequenceDiagram actor m as 用户程序 actor a as 分配器 actor h as heap堆内存 actor c as gc收集器 m-\u003e\u003ea: make/new等申请内存 a-\u003e\u003eh: malloc申请,初始化 c--\u003e\u003eh: free释放内存 栈空间,不用码农操作心, 大致了解连续栈,栈扩容,栈收缩一下\n反射,影响性能,不必要不使用.\n第一原则,任意类型变量转换成反射对象 flowchart LR int(int) --类型转换--\u003e i(interface对象) float(float) --类型转换--\u003e i bool(bool) --类型转换--\u003e i string(string) --类型转换--\u003e i struct(struct) --类型转换--\u003e i slice(slice) --类型转换--\u003e i array(array) --类型转换--\u003e i subgraph 反射对象 subgraph TypeOf ri(reflect.Type) end subgraph ValueOf rv(reflect.Value) end i --类型转换--\u003e ri i --类型转换--\u003e rv end 第二原则,反射对象可以获取 interface{} 变量 v := reflect.ValueOf(\u0026#34;st\u0026#34;) v.Interface().(string) flowchart LR rv(reflect.Value) --Interface方法--\u003e i(interface对象) i --类型断言--\u003e string(string) 第三原则,通过反射对象修改值,要传指针\nmystr := \u0026#34;old\u0026#34; //直接传mystr是不行的 vo := reflect.ValueOf(\u0026amp;mystr) vo.Elem().SetString(\u0026#34;new\u0026#34;) fmt.Println(mystr) for\nfor { } 相当于 for true { } for cond { } 相当于 for ; cond ; { } // RangeClause = [ ExpressionList \u0026#34;=\u0026#34; | IdentifierList \u0026#34;:=\u0026#34; ] \u0026#34;range\u0026#34; Expression . for-range 遍历之前都有copy数组/切片/map/chan, golang里面一切都是值拷贝,注意值拷贝带来的影响 循环变量每次都重新copy channel\n只有make一种创建方式,要不为nil,要不为有效chan\n有无缓冲?\n// 无缓冲 make(chan Type) // 有缓冲 make(chan Type, Len(buf)) 读取\n读取nil channel永远阻塞,Receiving from a nil channel blocks forever. 第二值为true,表示第一值为发送值,否则表示第一值zero value,系统构造的,暗示channel已经close channel关闭是指不能再写入,不影响读取.已经关闭的channel仍然能被读取 先入先出,先写入数据先被读取出来\nclose一个空指针或者已经被关闭channel,运行时都会直接崩溃并抛出异常:\nselect\n每个case一个Channel上非阻塞的收发操作; 多个case同时响应时,会随机执行一种情况; 如果default存在,则在case不响应时立即执行,否则阻塞等待case响应 defer\n退出函数之前执行 多次调用 defer执行顺序:先进后出,后进先出 defer func参数在调用时求值,仍旧是值传递 panic\npanicc后会立刻停止执行当前函数的剩余代码 仅执行本Goroutine中的defer 如果defer中没有recover处理,则整个程序退出(os.exit) 允许多次panic\u0026mdash;在执行defer时,还可以再次panic recover\n只有在 defer 中调用才会生效,其他地方无效\n可以中止 panic 造成的程序崩溃\n返回值为最近的panic参数,返回值为nil情况\npanic\u0026rsquo;s argument was nil; the goroutine is not panicking; recover was not called directly by a deferred function. 一次recover只能恢复一个panic\nfunc main() { defer println(\u0026#34;main exit\u0026#34;) go func() { defer func() { if reply := recover(); reply != nil { println(\u0026#34;recover:\u0026#34;, reply.(string)) } }() panic(\u0026#34;panic another\u0026#34;) }() go func() { defer func() { defer func() { if reply := recover(); reply != nil { println(\u0026#34;recover:\u0026#34;, reply.(string)) } }() if reply := recover(); reply != nil { println(\u0026#34;recover:\u0026#34;, reply.(string)) } panic(\u0026#34;panic continue\u0026#34;) }() panic(\u0026#34;panic begin\u0026#34;) }() time.Sleep(1 * time.Second) sync\nMutex,RWMutex flowchart LR l(Locker) --实现接口--\u003e m(Mutex) m --继承--\u003e rw(RWMutex) WaitGroup\n一些扩展使用 golang/sync/errgroup.Group带错误传播 golang/sync/singleflight.Group限制同时产生大量相同请求 pool临时对象复用池\nMap 多协程安全操作map,对内置map扩展\nOnce 保证只执行一次\nCond 信号量\n扩展使用 golang/sync/semaphore.Weighted带权重信号量 协程调度\nG-M-P模型 M是操作系统线程,由操作系统管理,GOMAXPROCS(一般是当前机器的核数)个活跃线程 G是Go运行时中用户态提供的线程,代表待执行的任务,表现为函数执行 P是线程和G的中间层,一个线程一个P,一个P一个本地G的队列,优先取本地的运行队列,然后取全局的运行队列 time\nTimer\u0026ndash;\u0026gt;单次事件,The Timer type represents a single event. Ticker\u0026ndash;\u0026gt;定时器,A Ticker holds a channel that delivers “ticks” of a clock at intervals. Duration\u0026ndash;\u0026gt;时间长度,例如:1分钟,10天 Time\u0026ndash;\u0026gt;时间点,例如:2022年1月2日03点4分15秒 Location\u0026ndash;\u0026gt;时区,例如:北京时间 tzdata\u0026ndash;\u0026gt;子包,打包时区数据库到程序,会增加程序二进制大小 每个处理器单独管理计时器并通过网络轮询器触发 golang.org/x/time/rate扩展包带了一个令牌桶限流算法 // token自动按速率产生,通过Wait/Allow消费token // 10是每秒可以向 Token 桶中产生多少 token // 100是 代表 Token 桶的容量大小 limiter := rate.NewLimiter(10, 100); json\nJSON 本身就是一种树形的数据结构,无论是序列化还是反序列化,都会遵循自顶向下的编码和解码过程,使用递归的方式处理 JSON 对象。 采用反射完成序列化/反序列化逻辑 struct对象可以tag调整json序列化/反序列化行为 net\nlisten(network, address string)\nThe network must be \u0026ldquo;tcp\u0026rdquo;, \u0026ldquo;tcp4\u0026rdquo;, \u0026ldquo;tcp6\u0026rdquo;, \u0026ldquo;unix\u0026rdquo; or \u0026ldquo;unixpacket\u0026rdquo;. For TCP networks, if the host in the address parameter is empty or a literal unspecified IP address, Listen listens on all available unicast and anycast IP addresses of the local system. To only use IPv4, use network \u0026ldquo;tcp4\u0026rdquo;. The address can use a host name, but this is not recommended, because it will create a listener for at most one of the host\u0026rsquo;s IP addresses. If the port in the address parameter is empty or \u0026ldquo;0\u0026rdquo;, as in \u0026ldquo;127.0.0.1:\u0026rdquo; or \u0026ldquo;[::1]:0\u0026rdquo;, a port number is automatically chosen. The Addr method of Listener can be used to discover the chosen port. Dial(network, address string)\nKnown networks are \u0026ldquo;tcp\u0026rdquo;, \u0026ldquo;tcp4\u0026rdquo; (IPv4-only), \u0026ldquo;tcp6\u0026rdquo; (IPv6-only), \u0026ldquo;udp\u0026rdquo;, \u0026ldquo;udp4\u0026rdquo; (IPv4-only), \u0026ldquo;udp6\u0026rdquo; (IPv6-only), \u0026ldquo;ip\u0026rdquo;, \u0026ldquo;ip4\u0026rdquo; (IPv4-only), \u0026ldquo;ip6\u0026rdquo; (IPv6-only), \u0026ldquo;unix\u0026rdquo;, \u0026ldquo;unixgram\u0026rdquo; and \u0026ldquo;unixpacket\u0026rdquo;. For TCP and UDP networks, the address has the form \u0026ldquo;host:port\u0026rdquo;. 扩展包golang.org/x/net有不少好功能实现\nhttp\n客户端,核心两个结构-Request,Response\nnet/http.Client net/http.Transport net/http.persistConn flowchart LR c(Client) --调用--\u003e t(Transport) t --调用--\u003ec(persistConn) 服务端,核心两个结构-Request,ResponseWriter\nnet/http.Server net/http.ServeMux net/http.Handler flowchart LR c(Server) --调用--\u003e t(ServeMux) t --调用--\u003ec(Handler) RoundTripper,代表一个http事务,给一个请求返回一个响应,可以自定义功能,例如:缓存responses\ntype RoundTripper interface { RoundTrip(*Request) (*Response, error) } net/http/httptrace,net/http/httptrace golang.org/x/image扩展bmp,webp等功能实现\ngolang.org/x/text扩展不少像gbk转utf8,高级文本搜索等功能\nio.Reader/Writer\nnet.Conn: 表示网络连接。 os.Stdin, os.Stdout, os.Stderr: 标准输入、输出和错误。 os.File: 网络,标准输入输出,文件的流读取。 strings.Reader: 字符串抽象成 io.Reader 的实现。 bytes.Reader: []byte抽象成 io.Reader 的实现。 bytes.Buffer: []byte抽象成 io.Reader 和 io.Writer 的实现。 bufio.Reader/Writer: 带缓冲的流读取和写入(比如按行读写)。 sql\ntype Driver interface { ... } type Conn interface { ... } type DB struct { // contains filtered or unexported fields } type Stmt struct { // contains filtered or unexported fields } type Tx struct { // contains filtered or unexported fields } 测试\n功能测试 // 文件名格式xxx_test.go // 函数名格式TestXxx,Test开头,第一个字母必须大写 // 函数参数必须是t *testing.T // 失败采用t.Fatalxxx,t.Errorxx输出 func TestAdd(t *testing.T) { if Add(10, 20) == 12 { t.Fatal(\u0026#34;failure\u0026#34;) } } # 启动 go test 压力测试 // 文件名格式xxx_test.go // 函数名格式BenchmarkXxx,Benchmark开头,第一个字母必须大写 // 函数参数必须是b *testing.B // 测试性能前提是功能正确,所以没有失败一说 func BenchmarkAdd(b *testing.B) { for i := 0; i \u0026lt; b.N; i++ { Add(rand.Int(), rand.Int()) } } # 启动, -bench pattern正则表达式,测试目标 go test -bench . 随机测试 // 文件名格式xxx_test.go // 函数名格式FuzzXxx,Fuzz开头,第一个字母必须大写 // 函数参数必须是f *testing.F // 失败采用t.Fatalxxx,t.Errorxx输出 func FuzzAdd(f *testing.F) { for i := 0; i \u0026lt; 10; i++ { // 随机种子语料 // f.Add参数个数及类型及顺序,必须和后面一样 f.Add(rand.Int(), rand.Int()) } // func(t *testing.T, left, right int), 参数除t之外, 参数个数及类型及顺序,必须和f.Add一样 f.Fuzz(func(t *testing.T, left, right int) { if Add(left, right) != left+right { t.Errorf( \u0026#34;%v+%v=%v, result:%v\u0026#34;, left, right, Add(left, right), left+right) } }) } # 启动,会一直执行下去,除非加上 -fuzztime 30s 指定运行时间 go test -fuzz Fuzz "
},
{
"uri": "/grpc/golang/",
"title": "golang示例",
"tags": [],
"description": "",
"content": "server package main import ( \u0026#34;context\u0026#34; \u0026#34;flag\u0026#34; \u0026#34;fmt\u0026#34; \u0026#34;log\u0026#34; \u0026#34;net\u0026#34; \u0026#34;google.golang.org/grpc\u0026#34; \u0026#34;google.golang.org/grpc/metadata\u0026#34; \u0026#34;google.golang.org/grpc/peer\u0026#34; com \u0026#34;xxx.site/myself/grpc-common\u0026#34; ) var ( GitHash = \u0026#34;Unkown\u0026#34; CompileTime = \u0026#34;Unkown\u0026#34; port = flag.Int(\u0026#34;port\u0026#34;, 8411, \u0026#34;默认端口\u0026#34;) ) // 定义服务端中间件 func middleware(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { log.Printf(\u0026#34;middleware ctx:%v\u0026#34;, ctx) log.Printf(\u0026#34;middleware req:%v\u0026#34;, req) log.Printf(\u0026#34;middleware info:%v\u0026#34;, info) log.Printf(\u0026#34;middleware handler:%v\u0026#34;, handler) resp, err = handler(ctx, req) log.Printf(\u0026#34;middleware resp:%v\u0026#34;, resp) log.Printf(\u0026#34;middleware err:%v\u0026#34;, err) return } type MathServer struct { com.UnimplementedMathServer } // 各种信息都通过ctx中valueCtx传递进来 // 由不同包获取转换 func (ms *MathServer) Add(ctx context.Context, req *com.AddReq) (*com.AddRsp, error) { log.Printf(\u0026#34;ctx:%v, req:%v\u0026#34;, ctx, req) if client, ok := peer.FromContext(ctx); ok { log.Printf(\u0026#34;client:%v\u0026#34;, client) } if ic, ok := metadata.FromIncomingContext(ctx); ok { log.Printf(\u0026#34;ic:%v\u0026#34;, ic) } if oc, ok := metadata.FromOutgoingContext(ctx); ok { log.Printf(\u0026#34;oc:%v\u0026#34;, oc) } if oc, ok := metadata.FromOutgoingContext(ctx); ok { log.Printf(\u0026#34;oc:%v\u0026#34;, oc) } sts := grpc.ServerTransportStreamFromContext(ctx) log.Printf(\u0026#34;sts:%v\u0026#34;, sts) return \u0026amp;com.AddRsp{ Result: req.Left + req.Right, }, nil } func main() { flag.Parse() // ct, err := credentials.NewServerTLSFromFile( // \u0026#34;grpc.xxx.site.pem\u0026#34;, // \u0026#34;grpc.xxx.site.key\u0026#34;, // ) // if err != nil { // log.Fatalf(\u0026#34;tls file;%v\u0026#34;, err) // } // tcp表示优先使用ipv6,其次ipv4,两者都能用 l, err := net.Listen(\u0026#34;tcp\u0026#34;, fmt.Sprintf(\u0026#34;:%d\u0026#34;, *port)) if err != nil { log.Fatalf(\u0026#34;fail listen tcp %d\u0026#34;, *port) } // 安装中间件 s := grpc.NewServer( // 默认没有采用安全传输ssl,tls // 增加证书认证 //grpc.Creds(ct), grpc.UnaryInterceptor(middleware), ) com.RegisterMathServer(s, \u0026amp;MathServer{}) log.Printf( \u0026#34;githash:%v, compile:%v,listen:%v\u0026#34;, GitHash, CompileTime, l.Addr()) err = s.Serve(l) if err != nil { log.Fatalf(\u0026#34;fail server:%v\u0026#34;, err) } } client package main import ( \u0026#34;context\u0026#34; \u0026#34;flag\u0026#34; \u0026#34;log\u0026#34; \u0026#34;time\u0026#34; \u0026#34;google.golang.org/grpc\u0026#34; \u0026#34;google.golang.org/grpc/credentials/insecure\u0026#34; com \u0026#34;xxx.site/myself/grpc-common\u0026#34; ) var ( GitHash = \u0026#34;unknown\u0026#34; CompileTime = \u0026#34;unknown\u0026#34; // addr = flag.String(\u0026#34;addr\u0026#34;, \u0026#34;dns:///grpc.xxx.site\u0026#34;, \u0026#34;默认服务端端口\u0026#34;) addr = flag.String(\u0026#34;addr\u0026#34;, \u0026#34;127.0.0.1:8411\u0026#34;, \u0026#34;默认服务端端口\u0026#34;) ) // 定义客户端中间件 func middleware(ctx context.Context, method string, req, reply interface{}, c *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { log.Printf(\u0026#34;middleware ctx:%v\u0026#34;, ctx) log.Printf(\u0026#34;middleware method:%v\u0026#34;, method) log.Printf(\u0026#34;middleware req:%v\u0026#34;, req) log.Printf(\u0026#34;middleware reply:%v\u0026#34;, reply) log.Printf(\u0026#34;middleware conn:%v\u0026#34;, c) log.Printf(\u0026#34;middleware invoker:%v\u0026#34;, invoker) for pos, opt := range opts { log.Printf(\u0026#34;middleware pos:%v, opt:%v\u0026#34;, pos, opt) } err := invoker(ctx, method, req, reply, c, opts...) log.Printf(\u0026#34;middleware err:%v\u0026#34;, err) return err } func main() { flag.Parse() // ct, err := credentials.NewClientTLSFromFile(\u0026#34;grpc.xxx.site.pem\u0026#34;, \u0026#34;grpc.xxx.site\u0026#34;) // if err != nil { // log.Fatalf(\u0026#34;err:%v\u0026#34;, err) // } conn, err := grpc.Dial( *addr, // 采用禁用安全传输,即没有ssl/tls grpc.WithTransportCredentials(insecure.NewCredentials()), // 采用证书,注意跨平台,linux amd64/apple m1芯片之间可能不能通讯 // grpc.WithTransportCredentials(ct), // 安装中间件 grpc.WithUnaryInterceptor(middleware), grpc.WithTimeout(time.Minute), ) if err != nil { log.Fatalf(\u0026#34;dial:%v, %v\u0026#34;, *addr, err) } defer conn.Close() client := com.NewMathClient(conn) req := com.AddReq{ Left: 10, Right: 20, } resp, err := client.Add(context.Background(), \u0026amp;req) if err != nil { log.Fatalf(\u0026#34;add fail:%v\u0026#34;, err) } log.Printf(\u0026#34;resp:%v\u0026#34;, resp.Result) } proto proto内容 syntax = \u0026#34;proto3\u0026#34;; option go_package = \u0026#34;./;common\u0026#34;; service Math { rpc Add(AddReq)returns(AddRsp){} } message AddReq { int64 left = 1; int64 right = 2; } message AddRsp { int64 result = 1; } 生成脚本 #!/bin/bash #--go-grpc_out表示启动protoc-gen-go-grpc插件 # --openapiv2_out 表示产生swagger.json protoc --go_out=. --go-grpc_out=. *.proto nginx ... server_names_hash_bucket_size 64; server { listen 443 ssl http2; server_name grpc.xxx.site; ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; ssl_certificate grpc.xxx.site.pem; ssl_certificate_key grpc.xxx.site.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { # grpc_pass localhost:9000; 等价于 grpc://127.0.0.1:8411 等价于 [::]:8411; # To use gRPC over SSL,就要带上grpcs: grpc_pass grpcs://[xxx]:8411; client_max_body_size 200M; } } ... "
},
{
"uri": "/grpc/",
"title": "grpc",
"tags": [],
"description": "",
"content": "相关网站 官网 github下载 protobuf-go插件 grpc-gateway-http转grpc buf-强化pb生成 rk-golang微服务框架 grpc-swift语言实现 #mac系统中采用brew,很可能已安装过 brew list | grep protobuf brew info protobuf golang使用图示 sequenceDiagram actor u as user actor pf as proto文件 actor pc as protoc actor pgg as protoc-gen-go actor pb as .pb.go文件 u-\u003e\u003epf: 编写message u-\u003e\u003epc: 启动 pc-\u003e\u003epf: 读取 pc-\u003e\u003epgg: 调用 pgg-\u003e\u003epb: 生成 u-\u003e\u003epb: 使用 生成文件 sequenceDiagram actor u as user actor pf as proto文件 actor pc as protoc actor pgg as protoc-gen-go actor pb as .pb.go文件 actor pggg as protoc-gen-go-grpc actor gpb as grpc.pb.go文件 u-\u003e\u003epf: 编写message,service u-\u003e\u003epc: 启动 pc-\u003e\u003epf: 读取 pc-\u003e\u003epgg: 调用 pgg-\u003e\u003epb: 生成 pc-\u003e\u003epggg: 调用 pggg-\u003e\u003egpb: 生成 u-\u003e\u003epb: 使用 u-\u003e\u003egpb: 使用 客户端使用 sequenceDiagram actor u as user actor gpb as grpc.pb.go文件 actor r as rpc服务器 u-\u003e\u003er: Dial()conn u-\u003e\u003egpb: Newclient(conn) u-\u003e\u003egpb: client.XXX() gpb-\u003e\u003e+r: conn发送请求 r--\u003e\u003e-gpb: return gpb--\u003e\u003eu: return 服务端使用 sequenceDiagram actor u as user actor t as tcp actor g as grpc actor gpb as grpc.pb.go文件 u-\u003e\u003et: Listen()conn u-\u003e\u003eg: NewServer u-\u003e\u003egpb: NewService u-\u003e\u003eg: RegService u-\u003e\u003e+g: Serve(conn) g-\u003e\u003eg: 等待客户端 实践示例 protoc --proto_path=IMPORT_PATH \\ --cpp_out=DST_DIR \\ --java_out=DST_DIR \\ --python_out=DST_DIR \\ --go_out=DST_DIR \\ --ruby_out=DST_DIR \\ --objc_out=DST_DIR \\ --csharp_out=DST_DIR \\ path/to/file.proto #--go_out表示启动protoc-gen-go插件 #proto文件和本脚本在同一目录,执行前要cd到本目录,防止出现各种相对路径找不到 #Could not make proto path relative: *.proto: No such file or directory protoc --cpp_out=../cpp --python_out=../python --go_out=../event *.proto #--go-grpc_out表示启动protoc-gen-go-grpc插件 protoc --go_out=../event --go-grpc_out=../event *.proto user.proto内容 syntax = \u0026#34;proto3\u0026#34;; option go_package = \u0026#34;./;event\u0026#34;; import \u0026#34;person.proto\u0026#34;; service User { rpc Reg(Person)returns(Person){} } example.proto内容 syntax = \u0026#34;proto3\u0026#34;; package example; //protoc-gen-go The import path must contain at least one period (\u0026#39;.\u0026#39;) or forward slash (\u0026#39;/\u0026#39;) character. //https://developers.google.com/protocol-buffers/docs/reference/go-generated //表示直接生成文件到go_out目录 option go_package = \u0026#34;./;event\u0026#34;; //vscode中vscode-proto3插件import提示无法找到other.proto //vscode直接打开other.proto所在目录,不要打开父目录 import \u0026#34;other.proto\u0026#34;; //单行注释 message Person { string name = 1; int32 id = 2; repeated string emails = 3; map\u0026lt;string, int32\u0026gt; dict = 4; repeated Order orders = 5; } /* 多行注释 */ message SearchResponse { message Result { string url = 1; string title = 2; repeated string snippets = 3; } repeated Result results = 1; } other.proto内容 syntax = \u0026#34;proto3\u0026#34;; package example; option go_package = \u0026#34;./;event\u0026#34;; message Order { int64 id = 1; uint64 date = 2; string customer = 3; double price = 4; string goods = 5; string remark = 6; } 数据类型 更多 gRPC + Opentracing + Zipkin 分布式链路追踪系统 "
},
{
"uri": "/other/harbor/",
"title": "harbor",
"tags": [],
"description": "",
"content": "简介 官网 github\nHarbor是VMware公司开源的企业级Docker Registry项目,其目标是帮助用户迅速搭建一个企业级的Docker Registry服务\nHarbor以 Docker 公司开源的Registry 为基础,提供了图形管理UI、基于角色的访问控制(Role Based AccessControl)、AD/LDAP集成、以及审计日志(Auditlogging)等企业用户需求的功能,同时还原生支持中文\nHarbor的每个组件都是以Docker 容器的形式构建的,使用docker-compose 来对它进行部署。用于部署Harbor 的docker- compose模板位于harbor/ docker- compose.yml\nlinux至少4核/8G\n# 下载离线安装包 ~/Downloads/harbor-offline-installer-v1.10.11.tgz 最好在linux机器上 # mac机器出现 ERROR: for portal Cannot start service portal: failed to initialize logging driver: dial tcp 127.0.0.1:1514: connect: connection refused ERROR: Encountered errors while bringing up the project. docker-compose脚本转发命令 docker compose自带,不必另外按装. harbor需要启动docker-compose相关依赖,所以需要一个转发 vim docker-compose #!/bin/bash docker compose $* 修改common.sh # 注释掉dockercompose检查 function check_dockercompose { return .... } 修改配置 # The IP address or hostname to access admin UI and registry service. # DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients. hostname: 修改自定义ip或域名 # 根据自已需求来配置http/https # http related config http: # port for http, default is 80. If https enabled, this port will redirect to https port port: 80 # https related config #https: # https port for harbor, default is 443 # port: 443 # The path of cert and key files for nginx # certificate: /your/certificate/path # private_key: /your/private/key/path [免费制品管理-nexus]https://www.sonatype.com/products/repository-oss-download "
},
{
"uri": "/nginx/http/",
"title": "HTTP模块",
"tags": [],
"description": "",
"content": "核心模块阶段 flowchart TD subgraph POST_READ realip(realip) end subgraph SERVER_REWRITE rewrite(rewrite) end subgraph FIND_CONFIG NULL(NULL) end subgraph REWRITE rewrite2(rewrite) end subgraph POST_REWRITE NULL2(NULL) end subgraph PREACCESS direction LR degradation(degradation) --\u003e limit_conn(limit_conn) limit_conn --\u003e limit_req(limit_req) limit_req --\u003e realip2(realip) end subgraph ACCESS direction LR access(access) --\u003e auth(auth) end subgraph POST_ACCESS NULL3(NULL) end subgraph PRECONTENT direction LR mirror(mirror) --\u003e try_files(try_files) end subgraph CONTENT direction LR static(static) --\u003e gzip_static(gzip_static) gzip_static --\u003e dav(dav) dav --\u003e autoindex(autoindex) autoindex --\u003e index(ndex) index --\u003e random_index(random_index) end subgraph LOG log(log) end POST_READ --\u003e SERVER_REWRITE SERVER_REWRITE --\u003e FIND_CONFIG FIND_CONFIG --\u003e REWRITE REWRITE --\u003e POST_REWRITE POST_REWRITE --\u003e PREACCESS PREACCESS --\u003e ACCESS ACCESS --\u003e POST_ACCESS POST_ACCESS --\u003e PRECONTENT PRECONTENT --\u003e CONTENT CONTENT --\u003e LOG POST_REWRITE阶段如果有rewrite,则会跳回到FIND_CONFIG阶段\n源代码中定义,如下图所示: FastCGI模块 sequenceDiagram actor n as nginx进程 actor c as CGI进程 n-\u003e\u003ec: begin_request处理开始 n-\u003e\u003ec: params请求参数 n-\u003e\u003e+c: stdin请求数据内容 c-\u003e\u003ec:请求处理 c--\u003e\u003e-n: stdout处理结果 c--\u003e\u003en: end_request处理结束 static模块 把请求url中path映射本地路径,读取本地文件返回客户端\n核心源代码,如下图所示: index模块 引入配置参数index,如下图所示: 请求url为目录时,把配置参数index值附加在url上,然后内部转跳\nstatic ngx_int_t ngx_http_index_handler(ngx_http_request_t *r) { ... if (index[i].name.data[0] == \u0026#39;/\u0026#39;) { return ngx_http_internal_redirect(r, \u0026amp;index[i].name, \u0026amp;r-\u0026gt;args); } ... ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r-\u0026gt;connection-\u0026gt;log, 0, \u0026#34;open index \\\u0026#34;%V\\\u0026#34;\u0026#34;, \u0026amp;path); ... return ngx_http_internal_redirect(r, \u0026amp;uri, \u0026amp;r-\u0026gt;args); } 转跳调试日志,如下图所示: "
},
{
"uri": "/other/hugo/",
"title": "hugo",
"tags": [],
"description": "",
"content": "简介 Hugo是由Go语言实现的静态网站生成器 官网 用户编辑内容文件,主题插件提供显示方式,hugo利用两者生成纯静态网站 Hugo靠shortcode扩展 用最新的mermaid.js替换Hugo-theme-learn主题自带的mermaid.js,可获取最新mermaid功能 config.toml中\u0026quot;home = [\u0026ldquo;HTML\u0026rdquo;, \u0026ldquo;RSS\u0026rdquo;, \u0026ldquo;JSON\u0026rdquo;]\u0026quot;,会产生index.json索引,不要删除 本地运行官网 git clone https://github.com/gohugoio/hugoDocs.git cd hugoDocs hugo -D server 默认访问http://localhost:1313/\n出现类似下面报错,hugoDocs中的config.toml增加timeout = 100000000000,单位ms\ntimeout默认值过短,原因为hugo生成网站时间超出默认配置\nError building site: \u0026#34;.../hugoDocs/content/en/troubleshooting/faq.md:1:1\u0026#34;: timed out initializing value. You may have a circular loop in a shortcode, or your site may have resources that take longer to build than the `timeout` limit in your Hugo config file. 优秀的主题网站(https://wowchemy.com/) 替代品-jekyll 官网(http://jekyllcn.com/)\n中文官网(http://jekyllcn.com/)\nmac自带的ruby,gem安装权限问题-示例本地运行fyne官网\nERROR: While executing gem ... (Gem::FilePermissionError) You don\u0026#39;t have write permissions for the /usr/bin directory. sudo gem install fastlane,采用sudo\ngem install fastlane \u0026ndash;user-install, 采用用户级别安装\nsudo gem install -n /usr/local/bin fastlane,同时指时路径\nbundle exec jekyll serve-如果出错\n常用参数\n# -w 表示监控文件变化及时生成网站 # --incremental 增量构建 # 启动过程会有点慢,需要等待一会儿 jekyll serve -w --port=4001 github项目中,如果只有__config.yml,没有Gemfile,则可能手动添加,方便本地跑起来 gem \u0026#39;github-pages\u0026#39;, group: :jekyll_plugins Ruby Version Manager-RVM (https://rvm.io/) curl -sSL https://get.rvm.io | bash -s stable "
},
{
"uri": "/golang/io/",
"title": "io包",
"tags": [],
"description": "",
"content": "基础 flowchart TB subgraph 单接口 direction LR r1(Reader)---w1(Writer)---c1(Closer)---s1(Seeker) end subgraph 双接口 direction LR rw(ReadWriter)---rc(ReadCloser)---rs(ReadSeeker)---wc(WriteCloser)---ws(WriteSeeker) end subgraph 三接口 direction LR rwc(ReadWriteCloser)---rsc(ReadSeekCloser)---rws(ReadWriteSeeker) end 单接口 --组合--\u003e 双接口 --组合--\u003e 三接口 Reader type Reader interface { // 读取len(p)字节到p里面 // 返回读取成功字节数 // eof表示正常结束 Read(p []byte) (n int, err error) } Writer type Writer interface { // 写入p里面内容,len(p)字节 // 返回写入成功字节数 Write(p []byte) (n int, err error) } 类型 flowchart TB subgraph Byte direction LR br(ByteReader)---bw(ByteWriter)---bc(ByteScanner) end subgraph Rune direction LR rr(RuneReader)---rw(ByteWriter)---rc(ByteScanner) end subgraph String direction LR sw(StringWriter) end 扩展 flowchart TB subgraph 附加 direction LR rf(ReaderFrom)---wt(WriterTo)---ra(ReaderAt)---wa(WriterAt) end subgraph 限制 direction LR lr(LimitedReader)---sr(SectionReader) end subgraph 内部 direction LR d(discard)---nc(nopCloser)---tr(teeReader镜像) mr(multiReader串联)---mw(multiWriter广播) pr(PipeReader就地读)--同个pipe,chan实现---pw(PipeWriter就地写) end 便利函数 WriteString(w Writer, s string) (n int, err error) ReadAll(r Reader) ([]byte, error) ReadFull(r Reader, buf []byte) (n int, err error) ReadAtLeast(r Reader, buf []byte, min int) (n int, err error) CopyN(dst Writer, src Reader, n int64) (written int64, err error) Copy(dst Writer, src Reader) (written int64, err error) CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) //扩展close接口 NopCloser(r Reader)ReadCloser //把r读出来内容写一份到w,镜像r到w TeeReader(r Reader, w Writer) Reader //最多读n个字节,达到就返回eof LimitReader(r Reader, n int64) Reader //串联起多个源头,按顺序依次读完 MultiReader(readers ...Reader) Reader //把w写入内容广播多个writers中 MultiWriter(writers ...Writer) Writer //就地成双读写,通过chan []byte实现 Pipe() (*PipeReader, *PipeWriter) // 切片扩容 if len(b) == cap(b) { // Add more capacity (let append pick how much). b = append(b, 0)[:len(b)] } "
},
{
"uri": "/golang/iris/",
"title": "iris",
"tags": [],
"description": "",
"content": "context中断原理 // I don\u0026#39;t set to a max value because we want to be able to reuse the handlers even if stopped with .Skip const stopExecutionIndex = -1 // StopExecution if called then the following .Next calls are ignored, // as a result the next handlers in the chain will not be fire. func (ctx *context) StopExecution() { ctx.currentHandlerIndex = stopExecutionIndex } // IsStopped checks and returns true if the current position of the context is -1, // means that the StopExecution() was called. func (ctx *context) IsStopped() bool { return ctx.currentHandlerIndex == stopExecutionIndex } func DefaultNext(ctx Context) { if ctx.IsStopped() { return } if n, handlers := ctx.HandlerIndex(-1)+1, ctx.Handlers(); n \u0026lt; len(handlers) { ctx.HandlerIndex(n) handlers[n](ctx) } } func (ctx *context) HandlerIndex(n int) (currentIndex int) { if n \u0026lt; 0 || n \u0026gt; len(ctx.handlers)-1 { return ctx.currentHandlerIndex } ctx.currentHandlerIndex = n return n } memcache中间件 import ( \u0026#34;bytes\u0026#34; \u0026#34;net/http\u0026#34; \u0026#34;sync\u0026#34; \u0026#34;github.com/bradfitz/gomemcache/memcache\u0026#34; \u0026#34;github.com/kataras/iris/v12/context\u0026#34; ) var memcacheClientMux sync.Mutex var memcacheClient *memcache.Client // TODO,要不要带上http头部,例如:数据类型html/json/js,Date,Cache-control等等 type middleResp struct { // 匿名包括,变相继承 http.ResponseWriter isOK bool key string expiration int32 // 如果匿名包括,变相继承会和ResponseWriter冲突,导致接口重复写 b bytes.Buffer } var StoreErrHandler func(error) func (mr *middleResp) writeStore() { if mr.b.Len() \u0026gt; 0 { err := memcacheClient.Set(\u0026amp;memcache.Item{ Key: mr.key, Flags: 0, Expiration: mr.expiration, Value: mr.b.Bytes(), }) if StoreErrHandler != nil { StoreErrHandler(err) } } } func (mr *middleResp) Write(body []byte) (int, error) { if mr.isOK \u0026amp;\u0026amp; memcacheClient != nil { _, err := mr.b.Write(body) if StoreErrHandler != nil { StoreErrHandler(err) } } return mr.ResponseWriter.Write(body) } func (mr *middleResp) WriteHeader(statusCode int) { mr.isOK = statusCode == http.StatusOK mr.ResponseWriter.WriteHeader(statusCode) } func MemcacheStore(server string, expireSecond int32) context.Handler { return MemcacheWrap(server, expireSecond, func(c context.Context) { c.Next() }) } func MemcacheWrap(server string, expireSecond int32, handler context.Handler) context.Handler { memcacheClientMux.Lock() defer memcacheClientMux.Unlock() if memcacheClient == nil { memcacheClient = memcache.New(server) } return func(c context.Context) { mr := \u0026amp;middleResp{ ResponseWriter: c.ResponseWriter().Naive(), key: c.Request().RequestURI, expiration: expireSecond, } c.ResponseWriter().BeginResponse(mr) handler(c) mr.writeStore() } } main使用 import ( \u0026#34;math/rand\u0026#34; \u0026#34;github.com/kataras/iris/v12\u0026#34; \u0026#34;github.com/kataras/iris/v12/middleware/recover\u0026#34; ) func main() { app := iris.New() booksAPI := app.Party( \u0026#34;/iris/books\u0026#34;, recover.New(), MemcacheStore(\u0026#34;127.0.0.1:11211\u0026#34;, 60), ) { booksAPI.Get(\u0026#34;/\u0026#34;, list) } app.Get(\u0026#34;/iris/other\u0026#34;, MemcacheWrap(\u0026#34;127.0.0.1:11211\u0026#34;, 60, other)) app.Listen(\u0026#34;:9090\u0026#34;) } func other(ctx iris.Context) { ctx.HTML( \u0026#34;\u0026lt;H1\u0026gt;%s, %v\u0026lt;/H1\u0026gt;\u0026#34;, ctx.Request().RequestURI, rand.Int(), ) } // Book example. type Book struct { Title string `json:\u0026#34;title\u0026#34;` } func list(ctx iris.Context) { books := []Book{ {\u0026#34;Mastering Concurrency in Go\u0026#34;}, {\u0026#34;Go Design Patterns\u0026#34;}, {\u0026#34;Black Hat Go\u0026#34;}, } // ctx.JSON(books) ctx.HTML(\u0026#34;%v\u0026#34;, books) // TIP: negotiate the response between server\u0026#39;s prioritizes // and client\u0026#39;s requirements, instead of ctx.JSON: // ctx.Negotiation().JSON().MsgPack().Protobuf() // ctx.Negotiate(books) } "
},
{
"uri": "/golang/log/",
"title": "log",
"tags": [],
"description": "",
"content": "日志常用示例 package main import ( \u0026#34;fmt\u0026#34; \u0026#34;io\u0026#34; \u0026#34;io/ioutil\u0026#34; \u0026#34;runtime\u0026#34; \u0026#34;strings\u0026#34; \u0026#34;time\u0026#34; rotatelogs \u0026#34;github.com/lestrrat-go/file-rotatelogs\u0026#34; \u0026#34;github.com/rifflock/lfshook\u0026#34; \u0026#34;github.com/sirupsen/logrus\u0026#34; ) func NewWriter(perfix string) io.Writer { w, err := rotatelogs.New( perfix+\u0026#34;.%Y%m%d.json\u0026#34;, // 建立软接 rotatelogs.WithLinkName(perfix), // 最多保存一星期 rotatelogs.WithMaxAge(7*24*time.Hour), // 一天切割一次 rotatelogs.WithRotationTime(24*time.Hour), ) if err != nil { panic(err) } return w } func InitLog(perfix string) { wm := lfshook.WriterMap{ logrus.DebugLevel: NewWriter(perfix + \u0026#34;_debug\u0026#34;), logrus.InfoLevel: NewWriter(perfix + \u0026#34;_info\u0026#34;), logrus.WarnLevel: NewWriter(perfix + \u0026#34;_warn\u0026#34;), logrus.ErrorLevel: NewWriter(perfix + \u0026#34;_error\u0026#34;), logrus.FatalLevel: NewWriter(perfix + \u0026#34;_fatal\u0026#34;), } logrus.AddHook(lfshook.NewHook( wm, \u0026amp;logrus.JSONFormatter{ CallerPrettyfier: func(f *runtime.Frame) (string, string) { var callerName, fileName string names := strings.SplitAfterN(f.File, perfix, 2) if len(names) \u0026gt; 1 { fileName = fmt.Sprintf(\u0026#34;%v;%v\u0026#34;, names[1], f.Line) } names = strings.SplitAfterN(f.Function, perfix, 2) if len(names) \u0026gt; 1 { callerName = names[1] } else { callerName = f.Function } return callerName, fileName }, PrettyPrint: true, }, )) logrus.SetOutput(ioutil.Discard) logrus.SetReportCaller(true) logrus.SetLevel(logrus.InfoLevel) logrus.WithFields(logrus.Fields{ \u0026#34;perfix\u0026#34;: perfix, \u0026#34;level\u0026#34;: logrus.GetLevel(), }).Warn(\u0026#34;日志初始化完成\u0026#34;) } "
},
{
"uri": "/mac/",
"title": "mac",
"tags": [],
"description": "",
"content": "码农必备 1. iTerm2 官网 配置cmd+u切换窗口透明 快速ssh\n创建一个profile脚本\nvim aliyun_iterm2_profile #填写模板内容,替换主机地址和密码,有可能第一次需要手动ssh root@xxxx,添加信任主机 #!/usr/bin/expect -f set user root set host ip set password pwd set timeout -1 spawn ssh $user@$host expect \u0026#34;*password:*\u0026#34; send \u0026#34;$password\\r\u0026#34; interact expect eof #增加可执行权限 chmod a+x aliyun_iterm2_profile 增加profile配置 command要从login shell-\u0026gt;command,上图中红色圈圈\n上图中红色方框填入第一步profile路径\n选择执行profile 替代品wrap\n安装时需要注册帐户,目前采用github授权,最好翻墙,否则会完成不了整个过程 2. brew 3.oh-my-zsh 官网 安装命令\n# 如果github访问不了,导致安装不了.则采用国内源安装 # /bin/zsh -c \u0026#34;$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)\u0026#34; sh -c \u0026#34;$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)\u0026#34; 常用插件\nplugins=( git docker extract dnf colored-man-pages command-not-found zsh-syntax-highlighting zsh-autosuggestions ) 历史记录采用年月日 HIST_STAMPS=\u0026#34;yyyy-mm-dd\u0026#34; 在~/.zshrc配置文件里设置ZSH_THEME为你的主题名称 ZSH_THEME=\u0026#34;robbyrussell\u0026#34; alias cd=\u0026#34;z\u0026#34; alias ping=\u0026#34;gping\u0026#34; alias ps=\u0026#34;procs -tree\u0026#34; alias du=\u0026#34;dust\u0026#34; alias df=\u0026#34;duf\u0026#34; alias ls=\u0026#34;exa -l --header --git\u0026#34; alias cat=\u0026#34;bat\u0026#34; eval \u0026#34;$(mcfly init zsh)\u0026#34; eval \u0026#34;$(zoxide init zsh)\u0026#34; zsh-syntax-highlighting zsh-autosuggestions extract 所有类型的文件解压一个命令x全搞定,再也不需要去记tar后面到底是哪几个参数了。 command-not-found 当你输入一条不存在的命令时,会自动查询这条命令可以如何获得 zoxide代替cd,可能不用启动z 提供一个 z 命令,在常用目录之间跳转。类似 autojump,但是不需要额外安装软件。 gping图形化显示ping结果 colored-man-pages 给你带颜色的 man 命令 docker 自带插件,可以实现docker命令补全和自动提示。 difft 自带语法比较,可以替代diff # Set git configuration for the current repository. git config diff.external difft # Set git configuration for all repositories git config --global diff.external difft 官方还提供了大量插件,大部分是针对某些功能的命令补全,如golang, python, pip, ruby, vagrant等。 # 显示最近10条历史命令 history [start] [end],正数从头,负数从尾 history -E -10 禁止自动更新 打开ohmyzsh(zsh) 的配置文件: ~/.zshrc 找到DISABLE_AUTO_UPDATE一行,将行首的注释\u0026#39;#\u0026#39;去掉,则可禁用ohmyzsh 自动检查更新。 4. vscode Visual Studio Code 有一个广泛的扩展市场,可以增加你的便利度。但在安装其中一个之前,最好先看看它是否还没有原生支持。随着时间的推移,包含改进和功能的每月发布更新,越来越多的 Visual Studio Code 扩展将不再需要。“有一堆扩展是 bulitin 的,你可以禁用所有你不需要的。进入扩展面板,搜索 @builtin”\n官网 优秀插件\ntabnine 有免费的AI助手编码,必须强赞一下\nCodeGeex 另一个自动生成代码\nshellman shellcheck shell-format(Alt+Shift+F) Code Runner\nNGINX Configuration Language Support\nGo for Visual Studio Code 支持一键生成单元测试\nPython\nMongoDB for VS Code\nRedis For VS Code\nMySQL\nvscode-drawio 直接在vscode中画图\ndocker\ntoml\nyaml\nvscode-pdf\nMarkdown PDF\nMarkdown Preview Mermaid Support\nvscode-proto3 在.vscode里面的settings.json设置protoc及相关路径\nJumpProtobuf 在.proto文件跳转f12键\nGit History\nGitLens — Git supercharged\nindent-rainbow\nvscode-icons用icon标识不同文件\nBetter Comments用不同色彩展示注释\nError Lens加强错误显示\nProject Dashboard把经常使用project固定到仪盘表中\nCodeSnap 是一个代码截图插件,只需选中项目中相应的代码段,即可快速创建代码的截图。\ntabnine-AI写代码帮助https://www.tabnine.com/\nCopilot-AI写代码帮助https://github.com/features/copilot/,tabnine类似\nOutput Colorizer *.log文件彩色输出\nvscode-database-client 高级使用需要收费 https://github.com/cweijan/vscode-database-client\nswagger preview-可以设置端口,直接测试接口\nHex Editor 以16进制格式查看文件\nRainbow CSV\nRainbow Brackets\nExcel Viewer\nPrettify JSON\nPath Autocomplete\nSQL Formatter\nRegex Previewer\nCode Spelling checker\nEnglish word hint\nvscode-fileheader 插入文件头注释,并且自动更新时间及作者\n自带markdown preview功能,cmd+shift+v\ntab/shift+tab整体正/反缩进,cmd+click跳进,ctrl+-跳回\n已知bug\nvscode打开目录层次不对,应该直接打开工程目录,不能打开父目录,否则报下面错误\ncould not import github.com/gomodule/redigo/redis (cannot find package \u0026#34;github.com/gomodule/redigo/redis\u0026#34; in any of /usr/local/go/src/github.com/gomodule/redigo/redis (from $GOROOT) /Users/.../gopath/src/github.com/gomodule/redigo/redis (from $GOPATH)) 自动保存可能会自动插入空格,在生成代码文件,需要注意,可能造成bug.\n修改go test timeout超时\n点击左下角齿轮-\u0026gt;设置 打开用户设置 在搜索栏中输入 go test timeout 可以找到 go.testTimeout为30s 工作空间 workspace多个目录一起打开,组合\n命令行直接调用\n命令面板(shift+cmd+p) 输入shell command 选择Install ‘code\u0026rsquo; command in PATH 命令行输入code . 代码片断\n打开vscode,file\u0026ndash;\u0026gt;preference(首选项)\u0026mdash;\u0026gt;user snippets(用户代码片断),输入python回车,添加如下代码: \u0026#34;Print with space lines\u0026#34;: { \u0026#34;prefix\u0026#34;: \u0026#34;ppp\u0026#34;, \u0026#34;body\u0026#34;: [ \u0026#34;print(\u0026#39;\\\\n\u0026#39;*2, $1)\u0026#34;, ], \u0026#34;description\u0026#34;: \u0026#34;Print with space lines\u0026#34; } 然后在编写python程序 时候,连续按ppp就可以快捷输出打印变量。\n5. fig大幅度提高效率 # 下载安装保存位置 ~/.local/bin 需要填写邮箱用来同步设置,否则没有效果 6. webp converter批量转换webp格式,appstore免费 7. Atomgithub开源免费文本编辑器,已死掉了 优秀插件 simplified-chinese-menu go-plus markdown-writer platformio-ide-terminal file-icons regex-railroad-diagram 8. sublimetext,闭源可免费使用文本编辑器 安装打开终端插件 terminus\ncmd+shift+p 然后输入 install package 输入 terminus\n配置key\n{ \u0026#34;keys\u0026#34;: [\u0026#34;ctrl+`\u0026#34;], \u0026#34;command\u0026#34;: \u0026#34;toggle_terminus_panel\u0026#34;, }, { \u0026#34;keys\u0026#34;: [\u0026#34;ctrl+shift+`\u0026#34;], \u0026#34;command\u0026#34;: \u0026#34;terminus_open\u0026#34;, \u0026#34;args\u0026#34;: { \u0026#34;cwd\u0026#34;: \u0026#34;${file_path:${folder}}\u0026#34; } }, 安装语法高亮nginx配置文件插件 sublime-nginx/Nginx Log Highlighter\ncmd+shift+p 然后输入 install package 输入 nginx 安装shell脚本语法高亮插件 Pretty Shell\ncmd+shift+p 然后输入 install package 输入 Pretty Shell 安装markdown插件 markdown Editing\ncmd+shift+p 然后输入 install package 输入 [markdown Editing] Rainbow CSV\nRainbow Brackets\nGit\nAutoFileName\nPretty JSON\nPretty Protocol buf\nProtocol Syntax Highlighting\nFileIcons\nSQL Formatter\nGitSyntaxes\nadvanced CSV\nJsFormat\nHTMLBeautify\ndocker file lint/ docker high light\n主题及color主题是两种,可以分开选择\n9. chrome,无google全家桶的chrome brew install --cask eloston-chromium 利用蓝牙传输文件 在\u0026quot;系统偏好设置\u0026quot;-\u0026gt;“蓝牙”开启功能\n等待发现蓝牙设备,连接设备,在设备上同意配对\nmac向设备传输文件使用“蓝牙文件交换”(位于“应用程序”文件夹的“实用工具”文件夹中)\n设备向mac传输文件,则mac设置蓝牙共享,\u0026ldquo;系统偏好设置\u0026rdquo;-\u0026gt;“共享”\n蓝牙传输超慢,建议采用局域网sftp,mac自带sftp服务\n无法验证开发者 解决办法:在Finder中找到应用程序,并找到该程序,右键-\u0026gt;打开 开机启动 Login Items\n在~/Library/Preferences/com.apple.loginitems.plist 在系统偏好设置的“用户与群组”下面进行设置,可以删除、添加、开启和关闭; Launchd Daemon,launchd来负责启动\n~/Library/LaunchAgents /Library/LaunchAgents /System/Library/LaunchAgents ~/Library/LaunchDaemons /Library/LaunchDaemons /System/Library/LaunchDaemons StartupItems\n/System/Library/StartupItems /Library/StartupItems 技巧 在命令行打开访达当前目录 open 特定目录 open . 截屏 shift+cmd+5 非常不错,谁用知道 朗读-读出所选内容(option+ecs),如果没有效果,则可能系统声音选择不对,本机器上反应有点慢,要等几秒才能读。 mac字体路径 /System/Library/Fonts,/Library/Fonts,ttf是mac和freetype共同推出的字体文件,ttc是ttf的集合文件(https://www.cnblogs.com/fortunely/p/16651504.html) 目前苹果有intel和M1芯片两种,软件下载安装时,注意Mac silicon/arm64/aarch指明适用M1芯片 xcode默认只有英文界面,不支持中文界面 iphone采用数据线连上mac,在新版的mac上没有iTunes,在访达偏好设置中有一个显示ios设备选项,否则无法显示出来! AppleID网络iCloud同步,前面打勾就会自动上传或下载同步iCloud空间中, iCloud云盘是iCloud空间一个目录,本地也有一个对应目录 照片也是iCloud空间一个目录,本地也有一个对应目录 其他华为,小米帐号iCloud空间都是类似的 查看端口 lsof -i tcp:8080 查看本机地址 # mac把Wi-Fi称为en0 ifconfig en0 修改hosts sudo vim /etc/hosts\n深色模式,保护眼睛 删除Microsoft Auto Update,烦人的更新提示\ncd /Library/Application Support/Microsoft/MAU2.0 sudo rm -rf Microsoft\\ AutoUpdate.app 树状显示目录tree\nbrew install tree tree 十六进制显示文件\n# xxd系统自带,-l只显示开头40字节 xxd -l 40 filename 访达/系统按键\n名称 作用 回车键 重命名文件夹或文件 command + o 打开文件 command + ↓ 打开文件 command + ↑ 进入当前目录的上一级目录 空格键 预览 imagemagick 图像处理神器\nbrew install imagemagick # 注意参数位置density是修饰pdf,否则会采用默认72dpi magick convert -density 300 enroll-sch.pdf -resize 1330x1900 -quality 100 ./photo/enroll-sch.jpg ssh免密登录远程 # 输入密码就能实现远程免密登陆,本质上pub文件内容加到远程机器~/.ssh/authorized_keys文件中 ssh-copy-id -i /root/.ssh/id_rsa.pub [email protected] 鼠标按windows滚动\n打开Mac系统偏好设置 在系统偏好设置界面,点击\u0026quot;鼠标\u0026quot; 进入鼠标的设置窗口,单击“光标与点按\u0026quot;标签 在光标与点按设置面板,将\u0026quot;滚动方向:自然\u0026quot;的勾选去掉即可 然后在滑动鼠标,即和windows的滚轮一样了 替换按键ctrl+alt mac电脑的默认字体-苹方字体,中文就是-苹方-简,有专门的\u0026quot;字体册\u0026quot;app管理\n编程仅好字体 Menlo, Monaco, \u0026lsquo;Courier New\u0026rsquo;, monospace 12大小\n"
},
{
"uri": "/other/machinelearn/",
"title": "machinelearn",
"tags": [],
"description": "",
"content": "常见框架 pytorch,1.12之后支持m1芯片\ntensorflow,目前支持m1芯片,需要打补丁tensorflow-plugin\nscikit-learn\nCore ML,苹果内置机器学习\npython机器学习包介绍 "
},
{
"uri": "/other/makefile/",
"title": "makefile",
"tags": [],
"description": "",
"content": "常见编译变量参数 SHELL := /usr/bin/env bash -o pipefail GIT_VERSION ?= $(shell git describe --always --tags --match \u0026#39;v*\u0026#39; --dirty) COMMIT ?= $(shell git rev-parse HEAD) BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD) BUILD_DATE ?= $(shell date +%s) BUILD_HOST ?= $(shell hostname) BUILD_USER ?= $(shell id -un) 变量不同赋值区别 = 是最基本的赋值 := 是覆盖之前的值 ?= 是如果没有被赋值过就赋予等号后面的值 += 是添加等号后面的值 "
},
{
"uri": "/other/markdown/",
"title": "markdown",
"tags": [],
"description": "",
"content": "标准化语法 github的扩展GFM 表情符号网站 语法: \u0026amp;#xCODE; 其中,CODE 可以从 Emoji Unicode Tables中查到。 例子: 查到了 表情对应的 Unicode 编码为 U+1F34E,则与此表情对应的 CODE 为 1F34E (舍弃前面的 U+)。 我们只需在 Markdown 文档中输入 🍎\n笔记 +1\n🍎\nwww.baidu.com\ngitbook写书工具,有各种插件\nmarkdown here写邮件\npandoc 不同标记语言间格式转换工具\nmarkdown有工具直接生成ppt\n有工具可以把markdown转成微信公众号需要的格式\n石墨文档,腾讯文档,语雀文档在线多人协作工具\ngitbook写书工具,有各种插件\nmdBook-rust实现的gitbook\nmkdocs,python开发的静态站点生成器\n"
},
{
"uri": "/memcached/",
"title": "memcached",
"tags": [],
"description": "",
"content": "官方文档 安装运行 #memcached依赖libevent brew install memcached brew services start memcached 启动选项:\n-d是启动一个守护进程; -m是分配给Memcache使用的内存数量,单位是MB; -u是运行Memcache的用户; -l是监听的服务器IP地址,可以有多个地址; -p是设置Memcache监听的端口,默认11211; -c是最大运行的并发连接数,默认是1024; -P是设置保存Memcache的pid文件。 -h是显示帮助 使用 telnet localhost 11211 存储命令 command \u0026lt;key\u0026gt; \u0026lt;flags\u0026gt; \u0026lt;expiration time\u0026gt; \u0026lt;bytes\u0026gt; \u0026lt;value\u0026gt; 参数说明如下:\ncommand set|add|replace|append|prepend key key 用于查找缓存值 flags 可以包括键值对的整型参数,客户机使用它存储关于键值对的额外信息 expiration time 在缓存中保存键值对的时间长度(以秒为单位,0 表示永远) bytes 在缓存中存储的字节数 value 存储的值(始终位于第二行) expiration time设置影响 缓存雪崩:短时间内大量键超时失效\n缓存击穿:缓存中没有键值\n确实不存在:用布隆过滤器优化 键超时:设置永不超时,受最大内存限制 命令 功能 set 没有则新增,有则更新,相当于add+replace add 新增键值,有则不操作 replace 替换存在键值,没有则不操作 append 向存在键值后面追加数据,不存在则不操作 prepend 向存在键值前面追加数据,不存在则不操作 查找命令 #多个key用空格隔开 command key key key 命令 功能 get 如果不存在,则返回空 gets 返回值增加CAS令牌 删除命令 delete key 增加减少命令 #decr incr command key value 已存在的 key(键) 的数字值进行自增或自减操作\n清空命令 flush_all [time] 可选参数 time,用于在指定的时间后执行清理缓存操作。\n源代码proto_proxy.c部分代码 static int process_request(mcp_parser_t *pr, const char *command, size_t cmdlen) { ... case 4: if (strncmp(cm, \u0026#34;gets\u0026#34;, 4) == 0) { cmd = CMD_GETS; type = CMD_TYPE_GET; token_max = 2; // don\u0026#39;t chew through multigets. ret = _process_request_simple(pr, 2); } else if (strncmp(cm, \u0026#34;incr\u0026#34;, 4) == 0) { cmd = CMD_INCR; ret = _process_request_simple(pr, 4); } else if (strncmp(cm, \u0026#34;decr\u0026#34;, 4) == 0) { cmd = CMD_DECR; ret = _process_request_simple(pr, 4); } else if (strncmp(cm, \u0026#34;gats\u0026#34;, 4) == 0) { cmd = CMD_GATS; type = CMD_TYPE_GET; ret = _process_request_gat(pr); } else if (strncmp(cm, \u0026#34;quit\u0026#34;, 4) == 0) { cmd = CMD_QUIT; } break; case 5: if (strncmp(cm, \u0026#34;touch\u0026#34;, 5) == 0) { cmd = CMD_TOUCH; ret = _process_request_simple(pr, 4); } else if (strncmp(cm, \u0026#34;stats\u0026#34;, 5) == 0) { cmd = CMD_STATS; // Don\u0026#39;t process a key; fetch via arguments. _process_tokenize(pr, token_max); } else if (strncmp(cm, \u0026#34;watch\u0026#34;, 5) == 0) { cmd = CMD_WATCH; _process_tokenize(pr, token_max); } break; case 6: if (strncmp(cm, \u0026#34;delete\u0026#34;, 6) == 0) { cmd = CMD_DELETE; ret = _process_request_simple(pr, 4); } else if (strncmp(cm, \u0026#34;append\u0026#34;, 6) == 0) { cmd = CMD_APPEND; ret = _process_request_storage(pr, token_max); } break; case 7: if (strncmp(cm, \u0026#34;replace\u0026#34;, 7) == 0) { cmd = CMD_REPLACE; ret = _process_request_storage(pr, token_max); } else if (strncmp(cm, \u0026#34;prepend\u0026#34;, 7) == 0) { cmd = CMD_PREPEND; ret = _process_request_storage(pr, token_max); } else if (strncmp(cm, \u0026#34;version\u0026#34;, 7) == 0) { cmd = CMD_VERSION; _process_tokenize(pr, token_max); } break; ... } 集群 多个节点,依赖代码库配合实现集群 减少扩容缩小节点影响,代码算法优化 内部结构 Slab Allocator解决了内存碎片,但由于分配的是特定长度的内存,因此浪费内存\n通讯协议 文本协议 直接用telnet,nc等工具都可以发送,\\r\\n表示换行,[]表示可选,会影响回包内容\n#存储类命令(set,add等) \u0026lt;command_name\u0026gt; \u0026lt;key\u0026gt; \u0026lt;flags\u0026gt; \u0026lt;exptime\u0026gt; \u0026lt;bytes\u0026gt;\\r\\n #存储内容 \u0026lt;data_block\u0026gt;\\r\\n #服务端回包,STORED成功,NOT_STORED失败 STORED\\r\\n NOT_STORED\\r\\n #删除 delete \u0026lt;key\u0026gt; [\u0026lt;time\u0026gt;] [noreply]\\r\\n #服务端回包 DELETED\\r\\n :表明执行成功 NOT_FOUND\\r\\n :表明这个键没有找到 #自增减命令(incr,decr) \u0026lt;command_name\u0026gt; \u0026lt;key\u0026gt; \u0026lt;value\u0026gt; [noreply]\\r\\n #服务端回包 NOT_FOUND\\r\\n :没有找到数据项 \u0026lt;value\u0026gt;\\r\\n :数据项的新数值,自增或自减以后的值 二进制协议 "
},
{
"uri": "/other/mermaid/",
"title": "mermaid-美人鱼",
"tags": [],
"description": "",
"content": "抄录官网示例,方便快速使用 Flowchart graph TD; A--\u0026gt;B; A--\u0026gt;C; B--\u0026gt;D; C--\u0026gt;D; graph TD; A--\u003eB; A--\u003eC; B--\u003eD; C--\u003eD; Sequence diagram sequenceDiagram participant Alice participant Bob Alice-\u0026gt;\u0026gt;John: Hello John, how are you? loop Healthcheck John-\u0026gt;\u0026gt;John: Fight against hypochondria end Note right of John: Rational thoughts \u0026lt;br/\u0026gt;prevail! John--\u0026gt;\u0026gt;Alice: Great! John-\u0026gt;\u0026gt;Bob: How about you? Bob--\u0026gt;\u0026gt;John: Jolly good! sequenceDiagram participant Alice participant Bob Alice-\u003e\u003eJohn: Hello John, how are you? loop Healthcheck John-\u003e\u003eJohn: Fight against hypochondria end Note right of John: Rational thoughts prevail! John--\u003e\u003eAlice: Great! John-\u003e\u003eBob: How about you? Bob--\u003e\u003eJohn: Jolly good! Gantt diagram gantt dateFormat YYYY-MM-DD title Adding GANTT diagram to mermaid excludes weekdays 2014-01-10 section A section Completed task :done, des1, 2014-01-06,2014-01-08 Active task :active, des2, 2014-01-09, 3d Future task : des3, after des2, 5d Future task2 : des4, after des3, 5d gantt dateFormat YYYY-MM-DD title Adding GANTT diagram to mermaid excludes weekdays 2014-01-10 section A section Completed task :done, des1, 2014-01-06,2014-01-08 Active task :active, des2, 2014-01-09, 3d Future task : des3, after des2, 5d Future task2 : des4, after des3, 5d Class diagram classDiagram Class01 \u0026lt;|-- AveryLongClass : Cool Class03 *-- Class04 Class05 o-- Class06 Class07 .. Class08 Class09 --\u0026gt; C2 : Where am i? Class09 --* C3 Class09 --|\u0026gt; Class07 Class07 : equals() Class07 : Object[] elementData Class01 : size() Class01 : int chimp Class01 : int gorilla Class08 \u0026lt;--\u0026gt; C2: Cool label classDiagram Class01 \u003c|-- AveryLongClass : Cool Class03 *-- Class04 Class05 o-- Class06 Class07 .. Class08 Class09 --\u003e C2 : Where am i? Class09 --* C3 Class09 --|\u003e Class07 Class07 : equals() Class07 : Object[] elementData Class01 : size() Class01 : int chimp Class01 : int gorilla Class08 \u003c--\u003e C2: Cool label Git graph gitGraph: options { \u0026#34;nodeSpacing\u0026#34;: 150, \u0026#34;nodeRadius\u0026#34;: 10 } end commit branch newbranch checkout newbranch commit commit checkout master commit commit merge newbranch gitGraph: options { \"nodeSpacing\": 150, \"nodeRadius\": 10 } end commit branch newbranch checkout newbranch commit commit checkout master commit commit merge newbranch Entity Relationship Diagram erDiagram CUSTOMER ||--o{ ORDER : places ORDER ||--|{ LINE-ITEM : contains CUSTOMER }|..|{ DELIVERY-ADDRESS : uses erDiagram CUSTOMER ||--o{ ORDER : places ORDER ||--|{ LINE-ITEM : contains CUSTOMER }|..|{ DELIVERY-ADDRESS : uses User Journey Diagram journey title My working day section Go to work Make tea: 5: Me Go upstairs: 3: Me Do work: 1: Me, Cat section Go home Go downstairs: 5: Me Sit down: 5: Me journey title My working day section Go to work Make tea: 5: Me Go upstairs: 3: Me Do work: 1: Me, Cat section Go home Go downstairs: 5: Me Sit down: 5: Me pie pie title Key elements in Product X \u0026#34;Calcium\u0026#34; : 42.96 \u0026#34;Potassium\u0026#34; : 50.05 \u0026#34;Magnesium\u0026#34; : 10.01 \u0026#34;Iron\u0026#34; : 5 pie title Key elements in Product X \"Calcium\" : 42.96 \"Potassium\" : 50.05 \"Magnesium\" : 10.01 \"Iron\" : 5 State diagrams stateDiagram-v2 [*] --\u0026gt; Still Still --\u0026gt; [*] Still --\u0026gt; Moving Moving --\u0026gt; Still Moving --\u0026gt; Crash Crash --\u0026gt; [*] stateDiagram-v2 [*] --\u003e Still Still --\u003e [*] Still --\u003e Moving Moving --\u003e Still Moving --\u003e Crash Crash --\u003e [*] "
},
{
"uri": "/mysql/",
"title": "mysql",
"tags": [],
"description": "",
"content": "SQL mysql没有完全实现sql标准\n不区分大小写,一般内置关键词,函数等采用大写,用户表,列,参数采用小写\n用分号作为结束语句标识,允许一行多条语句,一条语句多行.\n有不同模式,建议采用strict mode\n默认autocommit,除非显式取消\n注释\n单行: 以#开头,到行结束 单行: 以\u0026ndash; 开头,到行结束 多行: /开头,/结束,c风格 字符集(Character)与校对规则(Collation)\n字符集都对应着一个默认的校对规则,也可以对应多个规则 变量character_set_server记录服务器默认值,mysql8.0默认是utf8mb4(可储各种表情符号,最长4字节) 每个库/表/字段可单独指定,库不指定则用服务器,表不指定则用库,字段不指定则用表 character_set_client服务器认为客户端发送过来的sql语句的编码 character_set_conneciton执行sql内部编码,所以服务器把客户端发送的sql从character_set_client转为character_set_conneciton character_set_results 返回结果集 客户端用连接参数一次性指定这三个值character_set_client, character_set_results, character_set_connection 自带4个数据库\ninformation_schema 保存所有数据库/表/列/索引/权限等信息 performance_schema 收集数据库服务器性能参数,资源消息,资源等待 sys 存储来自performance_schema,简化说明,易于DBA理解 mysql 存储库用户,权限,关键字等mysql自已需要必要信息 程序表\n名称 作用 mysqld 服务器 mysqld_safe 用来启动mysqld的脚本 mysql.server 系统启动脚本,调用mysqld_safe脚本 mysqld_multi 允许同时多个mysqld进程 mysql 客户端 mysqladmin 客户端管理数据库 mysqldump 客户端导出数据 mysqlimport 客户端导入数据 联表\n... joined_table: { table_reference {[INNER | CROSS] JOIN | STRAIGHT_JOIN} table_factor [join_specification] | table_reference {LEFT|RIGHT} [OUTER] JOIN table_reference join_specification | table_reference NATURAL [INNER | {LEFT|RIGHT} [OUTER]] JOIN table_factor } join_specification: { ON search_condition | USING (join_column_list) } ... JOIN, CROSS JOIN, and INNER JOIN等价,和sql标准不相同\n// 简化翻译sql逻辑 // select tbl1.col1, tbl2.col2 from tbl1 inner join tbl2 using(col3) where tbl1.col1 in (5, 6); // 内联没有指明驱动表,优化器会根据过滤行数少作为驱动表,这里假设选择tbl1作为驱动表 // STRAIGHT_JOIN用来指定哪个表作为驱动表,示例如下: // select tbl1.col1, tbl2.col2 from tbl1 STRAIGHT_JOIN tbl2 using(col3) where tbl1.col1 in (5, 6); outer_iter = iterator over tbl1 where col1 in (5, 6) outer_row = outer_iter.next while outer_row inner_iter = iterator over tbl2 where col3 = outer_row.col3 inner_row = inner_iter.next while inner_row output [ outer_row.col1, inner_row.col2] inner_row = inner_iter.next end outer_row = outer_iter.next end LEFT, RIGHT [OUTER] JOIN,外连关键词(outer)可省略,写不写都是一样功能\n// 简化翻译sql逻辑 // select tbl1.col1, tbl2.col2 from tbl1 left outer join tbl2 using(col3) where tbl1.col1 in (5, 6); // left,right表明了哪个表作为驱动表 outer_iter = iterator over tbl1 where col1 in (5, 6) outer_row = outer_iter.next while outer_row inner_iter = iterator over tbl2 where col3 = outer_row.col3 inner_row = inner_iter.next if inner_row while inner_row output [ outer_row.col1, inner_row.col2] inner_row = inner_iter.next end else output [ outer_row.col1, null] end outer_row = outer_iter.next end FULL OUTER JOIN暂不支持\nNATURAL表示join_specification采用USING(join_column_list),不用手动写出来,join_column_list选取两个表都有的列名\nEXPLAIN/DESCRIBE/DESC 作用一样的\n-- 获取表结构/信息 {EXPLAIN | DESCRIBE | DESC} tbl_name [col_name | wild] -- 获取执行计划信息 {EXPLAIN | DESCRIBE | DESC} [explain_type] {explainable_stmt | FOR CONNECTION connection_id} -- 获取更详执行计划细信息 {EXPLAIN | DESCRIBE | DESC} ANALYZE [FORMAT = TREE] select_statement explain_type: { FORMAT = format_name } format_name: { TRADITIONAL | JSON | TREE } explainable_stmt: { SELECT statement | TABLE statement | DELETE statement | INSERT statement | REPLACE statement | UPDATE statement } help语句\n-- 显示select语句语法,较便利 HELP \u0026#39;select\u0026#39; 数据类型 数字,默认是有符号(SIGNED),无符号(UNSIGNED)要特别指定\n类型 字节数 TINYINT 1 SMALLINT 2 MEDIUMINT 3 INT 4 BIGINT 8 FLOAT 4 DOUBLE 8 DECIMAL 二进制存储 其他有一些别名 All arithmetic is done using signed BIGINT or DOUBLE values 时间\n类型 范围 零值 说明 DATE \u0026lsquo;1000-01-01\u0026rsquo;到'9999-12-31\u0026rsquo; \u0026lsquo;0000-00-00\u0026rsquo; 年月日 TIME \u0026lsquo;-838:59:59.000000\u0026rsquo;到'838:59:59.000000\u0026rsquo; \u0026lsquo;00:00:00\u0026rsquo; 时分秒 DATETIME \u0026lsquo;1000-01-01 00:00:00\u0026rsquo;到'9999-12-31 23:59:59\u0026rsquo; 0000-00-00 00:00:00 年月日时分秒 TIMESTAMP \u0026lsquo;1970-01-01 00:00:01.000000\u0026rsquo;到'2038-01-19 03:14:07.999999\u0026rsquo; 0000-00-00 00:00:00 时间戳 YEAR 别用 \u0026lsquo;0000\u0026rsquo; 别用,有坑 TIME,DATETIME,TIMESTAMP默认精确到秒,增加参数指定精确小数,最多到6位 create table mytime ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, -- \u0026#39;00:00:00.000000\u0026#39; t TIME(6) not null, -- \u0026#39;1000-01-01 00:00:00.00000\u0026#39; dt DATETIME(5) not null, ts TIMESTAMP(4) not null, t2 TIME(3) not null, dt2 DATETIME(2) not null, ts2 TIMESTAMP(1) not null ); DATETIME,TIMESTAMP都可以用DEFAULT CURRENT_TIMESTAMP指定默认值 字符串\nchar\nCHAR(len),VARCHAR(len)最多储存len个char字符,储存占用字节由字符集处理 char固定大小,varchar变化大小,指消费储存占用字节 varchar默认去尾空格空白 binary\nBINARY(len),VARCHAR(len)最多储存len个字节,字符集转化字符后字节 短字符串\n字符存储 字节存储 char binary varchar varbinary 长字符串\ntext(字符存储,类似char) blob(字节存储,类似binary) tinytext tinyblob mediumtext mediumblob text blob longtext longblob json\ncreate table js(v json); insert into js(v) values(\u0026#39;[10, 20, 30]\u0026#39;); insert into js(v) values(\u0026#39;{\u0026#34;a\u0026#34;:10}\u0026#39;); 分区表 分类类型\nRANGE,分区必须指定范围 CREATE TABLE employees ( id INT NOT NULL, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULL DEFAULT \u0026#39;1970-01-01\u0026#39;, separated DATE NOT NULL DEFAULT \u0026#39;9999-12-31\u0026#39;, job_code INT NOT NULL, store_id INT NOT NULL ) PARTITION BY RANGE (store_id) ( PARTITION p0 VALUES LESS THAN (6), PARTITION p1 VALUES LESS THAN (11), PARTITION p2 VALUES LESS THAN (16), PARTITION p3 VALUES LESS THAN MAXVALUE ); LIST,分区必须指定集合,每条记录只能属于其中一个集合 CREATE TABLE person ( id INT NOT NULL, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULL DEFAULT \u0026#39;1970-01-01\u0026#39;, separated DATE NOT NULL DEFAULT \u0026#39;9999-12-31\u0026#39;, job_code INT, store_id INT ) PARTITION BY LIST(store_id) ( PARTITION pNorth VALUES IN (3, 5, 6, 9, 17), PARTITION pEast VALUES IN (1, 2, 10, 11, 19, 20), PARTITION pWest VALUES IN (4, 12, 13, 14, 18), PARTITION pCentral VALUES IN (7, 8, 15, 16) ); HASH,注意hash分布,造成热点分区 CREATE TABLE worker ( id INT NOT NULL, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULL DEFAULT \u0026#39;1970-01-01\u0026#39;, separated DATE NOT NULL DEFAULT \u0026#39;9999-12-31\u0026#39;, job_code INT, store_id INT ) PARTITION BY [LINEAR] HASH(store_id) PARTITIONS 4; -- LINEAR 带上则指定hash算法 KEY,隐式hash,服务器采用hash(key)实现,可任意类型 CREATE TABLE tm1 (s1 CHAR(32) PRIMARY KEY) PARTITION BY KEY(s1) PARTITIONS 10; 分区pruning\n# where子句能够转化为下面两种,optimizer优化器就能选定分区,省去不必要查找 partition_column = constant partition_column IN (constant1, constant2, ..., constantN) # select update delete 都需要注意 # insert 只会影响一个分区,不必考虑分区修剪 Subpartitioning 子分区\nselect语法\nSELECT [ALL | DISTINCT | DISTINCTROW ] [HIGH_PRIORITY] [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] select_expr [, select_expr] ... [into_option] [FROM table_references [PARTITION partition_list]] [WHERE where_condition] [GROUP BY {col_name | expr | position}, ... [WITH ROLLUP]] [HAVING where_condition] [WINDOW window_name AS (window_spec) [, window_name AS (window_spec)] ...] [ORDER BY {col_name | expr | position} [ASC | DESC], ... [WITH ROLLUP]] [LIMIT {[offset,] row_count | row_count OFFSET offset}] [into_option] [FOR {UPDATE | SHARE} [OF tbl_name [, tbl_name] ...] [NOWAIT | SKIP LOCKED] | LOCK IN SHARE MODE] [into_option] into_option: { INTO OUTFILE \u0026#39;file_name\u0026#39; [CHARACTER SET charset_name] export_options | INTO DUMPFILE \u0026#39;file_name\u0026#39; | INTO var_name [, var_name] ... } insert [INTO] tbl_name [PARTITION (partition_name [, partition_name] ...)] [(col_name [, col_name] ...)] { {VALUES | VALUE} (value_list) [, (value_list)] ... } [AS row_alias[(col_alias [, col_alias] ...)]] [ON DUPLICATE KEY UPDATE assignment_list] INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE] [INTO] tbl_name [PARTITION (partition_name [, partition_name] ...)] [AS row_alias[(col_alias [, col_alias] ...)]] SET assignment_list [ON DUPLICATE KEY UPDATE assignment_list] INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE] [INTO] tbl_name [PARTITION (partition_name [, partition_name] ...)] [(col_name [, col_name] ...)] [AS row_alias[(col_alias [, col_alias] ...)]] {SELECT ... | TABLE table_name | VALUES row_constructor_list } [ON DUPLICATE KEY UPDATE assignment_list] 实例解释\n-- 每列采用默认值插入 INSERT INTO tbl_name () VALUES(); -- 允许后面出现的列引用前面列值 -- AUTO_INCREMENT在列赋值之后,所以引用此列值会为0 INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2); -- With INSERT ... SELECT插入多行,速度较快,ta表中AUTO_INCREMENT仍然自增,先赋值才执行AUTO_INCREMENT -- 等价于 INSERT INTO ta SELECT * FROM tb INSERT INTO ta TABLE tb; -- 附上DUPLICATE,要求a,b,c至少一个是唯一或主键 -- 当多个是唯一或主键时,任选一个执行 -- UPDATE t1 SET c=c+1 WHERE a=1 OR b=2 LIMIT 1; INSERT INTO t1 (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1; -- VALUES(colname)用来引用指定列插入值,相当于下面两句结果 -- INSERT INTO t1 (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=3; -- INSERT INTO t1 (a,b,c) VALUES (4,5,6) ON DUPLICATE KEY UPDATE c=9; INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b); delete\n删除自增字段不会重用\n单表\nDELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name [[AS] tbl_alias] [PARTITION (partition_name [, partition_name] ...)] [WHERE where_condition] -- 删除顺序,配合limit可用来分段删除 [ORDER BY ...] -- 限制删除行数,通常用来防止删除影响其他业务,每次只删除部分,多次删除 [LIMIT row_count] 多表 DELETE [LOW_PRIORITY] [QUICK] [IGNORE] -- 删除在from之前的表中行 tbl_name[.*] [, tbl_name[.*]] ... FROM table_references [WHERE where_condition] DELETE [LOW_PRIORITY] [QUICK] [IGNORE] -- 删除在from子句中表的行 FROM tbl_name[.*] [, tbl_name[.*]] ... USING table_references [WHERE where_condition] 大表删除多行,InnoDB引擎优化 -- 把不删除数据插入一张新表中 INSERT INTO t_copy SELECT * FROM t WHERE ... ; -- 新表,老表互换名字 RENAME TABLE t TO t_old, t_copy TO t; -- 删除老表,但名字为改名后 DROP TABLE t_old; replace\nREPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name [PARTITION (partition_name [, partition_name] ...)] [(col_name [, col_name] ...)] { {VALUES | VALUE} (value_list) [, (value_list)] ... | VALUES row_constructor_list } REPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name [PARTITION (partition_name [, partition_name] ...)] SET assignment_list REPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name [PARTITION (partition_name [, partition_name] ...)] [(col_name [, col_name] ...)] {SELECT ... | TABLE table_name} update UPDATE [LOW_PRIORITY] [IGNORE] table_reference SET assignment_list [WHERE where_condition] [ORDER BY ...] [LIMIT row_count] 特有功能 show databases; use databasename; show tables; describe tablename; #从本地导入数据 #windows用\\r\\n,mac用\\r,linux用\\n LOAD DATA LOCAL INFILE \u0026#39;/path/pet.txt\u0026#39; INTO TABLE tablename LINES TERMINATED BY \u0026#39;\\r\\n\u0026#39;; #mysql查变量,获取mysql默认行为,各种参数值 SHOW VARIABLES; #只关注想要的 SHOW VARIABLES LIKE \u0026#39;%timeout%\u0026#39; # 查看客户端连接详情,用来检查执行客户端的sql情况,特别慢查询,多连接 show full processlist; #客户端连接数 select client_ip,count(client_ip) as client_num from (select substring_index(host,\u0026#39;:\u0026#39; ,1) as client_ip from information_schema.processlist ) as connect_info group by client_ip order by client_num desc; #执行sql时间倒序 select * from information_schema.processlist where Command != \u0026#39;Sleep\u0026#39; order by Time desc; # 查看表创建语句 show create table xx; #mysql关闭安全模式 show variables like \u0026#39;SQL_SAFE_UPDATES\u0026#39;; SET SQL_SAFE_UPDATES = 0; #通用日志,调试好帮手,需要root权限 show variables like \u0026#39;%general%\u0026#39;; set @@global.general_log=1; set @@global.general_log=0; # 设置连接超时时间,下次登陆有效 show variables like \u0026#39;%timeout%\u0026#39;; --604800=60*60*24 set @@GLOBAL.interactive_timeout=604800; set @@GLOBAL.wait_timeout=604800; # 查看默认引擎 show engines; # 查询表中重复数据 select col from table group by col having count(col) \u0026gt; 1; # 带忽略重复的插入 insert ignore into table(name) value(\u0026#39;xx\u0026#39;) # 常用时间函数 FROM_UNIXTIME(unix_timestamp)是MySQL里的时间函数。 UNIX_TIMESTAMP(\u0026#39;2018-09-17\u0026#39;) 是与之相对正好相反的时间函数 。 # IF条件表达式 IF(expr1,expr2,expr3) --如果 expr1 为真(expr1 \u0026lt;\u0026gt; 0 以及 expr1 \u0026lt;\u0026gt; NULL),那么 IF() 返回 expr2,否则返回 expr3。IF() 返回一个数字或字符串,这取决于它被使用的语境: #concat把int转varchar类型 update user set nickname = concat(id,\u0026#39;号\u0026#39;) where id \u0026gt; 0; # 字符串替换 update user set nickname = REPLACE(id,\u0026#39;old\u0026#39;, \u0026#39;now\u0026#39;) where id \u0026gt; 0 # 查询数据库占用空间及索引空间 # Binlog,阿里云的rds默认把它也计算在内,要手动设置控制大小.大量数据删除时,会突然增加Binlog文件 select TABLE_NAME, concat(truncate(data_length/1024/1024,2),\u0026#39; MB\u0026#39;) as data_size, concat(truncate(index_length/1024/1024,2),\u0026#39; MB\u0026#39;) as index_size from information_schema.tables where TABLE_SCHEMA = \u0026#39;databaseName\u0026#39; # 修改root密码 killall mysqld mysqld_safe --skip-grant-tables \u0026amp; update mysql.user set password=PASSWORD(\u0026#39;newpassword\u0026#39;) where user=\u0026#39;root\u0026#39;; flush privileges; mysqld_safe \u0026amp; # 设置默认字符集 mysql -u user -D db --default-character-set=utf8 -p explain优化sql explain select col from table where con group by xx order by yy; 输出说明:\ntable 显示该语句涉及的表 type 这列很重要,显示了连接使用了哪种类别,有无使用索引,反映语句的质量。 possible_keys 列指出MySQL能使用哪个索引在该表中找到行 key 显示MySQL实际使用的键(索引)。如果没有选择索引,键是NULL。 key_len 显示MySQL决定使用的键长度。如果键是NULL,则长度为NULL。使用的索引的长度。在不损失精确性的情况下,长度越短越好 ref 显示使用哪个列或常数与key一起从表中选择行。 rows 显示MySQL认为它执行查询时必须检查的行数。 extra 包含MySQL解决查询的详细信息。 其中:Explain的type显示的是访问类型,是较为重要的一个指标,结果值从好到坏依次是: system \u0026gt; const \u0026gt; eq_ref \u0026gt; ref \u0026gt; fulltext \u0026gt; ref_or_null \u0026gt; index_merge \u0026gt; unique_subquery \u0026gt; index_subquery \u0026gt; range \u0026gt; index \u0026gt; ALL(优\u0026ndash;\u0026gt;差) 一般来说,得保证查询至少达到range级别,最好能达到ref,否则就可能会出现性能问题 碎片产生的原因 表的存储会出现碎片化,每当删除了一行内容,该段空间就会变为空白、被留空,而在一段时间内的大量删除操作,会使这种留空的空间变得比存储列表内容所使用的空间更大; 当执行插入操作时,MySQL会尝试使用空白空间,但如果某个空白空间一直没有被大小合适的数据占用,仍然无法将其彻底占用,就形成了碎片; 当MySQL对数据进行扫描时,它扫描的对象实际是列表的容量需求上限,也就是数据被写入的区域中处于峰值位置的部分; 清除不要数据,记得要optimize table xx;不然空间仍旧占用. 例如: 一个表有1万行,每行10字节,会占用10万字节存储空间,执行删除操作,只留一行,实际内容只剩下10字节,但MySQL在读取时,仍看做是10万字节的表进行处理,所以,碎片越多,就会越来越影响查询性能。\n免密码登陆 利用.my.cnf\nvi ~/.my.cnf [client] # 注意mysql的库中user表,localhost和127.0.0.1区别 host = \u0026#34;127.0.0.1\u0026#34; user = \u0026#34;user\u0026#34; password = \u0026#34;pwd\u0026#34; database = \u0026#34;xx\u0026#34; 利用命令行参数,或者别名\nmysql -h localhost -u root -p xxx 小知识 哪个是JOIN,哪个是过滤器? -- 隐式内联,不好理解容易出错,不建议 -- a,b ==\u0026gt; inner join 简写 -- a.ID = b.ID ==\u0026gt; 用来关联,不是过滤, SELECT * FROM a,b WHERE a.ID = b.ID -- 显示内联,建议这种 -- a JOIN b ==\u0026gt; inner join SELECT * FROM a JOIN b ON a.ID = b.ID -- USING(ID) == \u0026gt; ON a.ID = b.ID -- 要求两个表都存在ID列 SELECT * FROM a JOIN b USING(ID) 分组连接 select sch_id, count(sch_id) as c, GROUP_CONCAT(sch_name) from sch_basic_info sbi group by sch_id HAVING count(sch_id) \u0026gt; 1 order by c desc; select GROUP_CONCAT(sch_name) from sch_basic_info sbi group by sch_id HAVING count(sch_id) \u0026gt; 1; 支持opengis,geometry Geometry (noninstantiable) Point (instantiable) Curve (noninstantiable) LineString (instantiable) Line LinearRing Surface (noninstantiable) Polygon (instantiable) GeometryCollection (instantiable) MultiPoint (instantiable) MultiCurve (noninstantiable) MultiLineString (instantiable) MultiSurface (noninstantiable) MultiPolygon (instantiable) 附录 表一般不超过2000万行 postgresql-开源替代品 c++-图数据库 golang-图数据库 "
},
{
"uri": "/nginx/",
"title": "nginx",
"tags": [],
"description": "",
"content": "http模块 源码安装剖析 常用技巧 Nginx-中国开源社区 HTTP-V3-Module brotli-替代gzip压缩算法,更快更省时 caddy-nginx替代品 可视化配置展示-nginxconfig 动态配置+内置应用支持-nginxunit 动态配置-traefik openssl爆出各种重大问题,大厂都自已搞了一个分支 谷歌的openssl-boringssl OpenBSD重构openssl-libressl 谷歌新压缩算法-brotli "
},
{
"uri": "/python/",
"title": "python",
"tags": [],
"description": "",
"content": "重要网站 官网 python2已死,不要再学再用啦!!!\npypi 官方第三方包网站,你绝对值得拥有!\nvenv-解决不同项目依赖不同版本包,依赖冲突 # 源码编译安装 # 官网 python.org 下载压缩包,解压 # 然后,在./configure的时候,需要加上 --enable-optimizations参数,这样才能启用很多功能。 # 创建tutorial-env目录,复制一份python相关环境 python3 -m venv tutorial-env # windows执行,激活虚拟环境 tutorial-env\\Scripts\\activate.bat # Macos/unix执行,激活虚拟环境 source tutorial-env/bin/activate 安装pip #看看pip是否安装,现在一般都安装的,特别是采用brew,安装包之类 python3 -m pip --version #手动安装,一般不用 python3 -m ensurepip --default-pip # 升级pip python3 -m pip install --upgrade pip # 在某些情况下,我们需要查看第三方包的依赖包和被依赖包 # 命令输出的 Requires 和 Required-by pip show pkg_name # 能显示所有的依赖包及其子包,推荐用这个 pip deptree -p pkg_name # 永久性切换国内清华源 pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple # 换回默认源 pip3 config unset global.index-url # 本次下载python中的Django包,这里使用的是豆瓣源 pip3 install django -i http://pypi.douban.com/simple requirements.txt可以通过pip命令自动生成和安装 生成requirements.txt文件 # 产生整个python环境的安装依赖,方便移值及复制 pip freeze \u0026gt; requirements.txt 安装requirements.txt依赖包: pip install -r requirements.txt 安装常用库 # pylint执行pep8规范 pip3 install pylint pylint xxx.py # 更严格的检测flake8 pip3 install flake8 flake8 xx.py # 强制统一代码风格 pip install black black code_dir/xxx.py # yapf是google开源的格式化代码工具 pip install yapf # 统一import格式 pip3 install isort isort xx.py # 静态检查 pip3 install mypy mypy xxx.py # 比内置unittest更好用单元测试 pip3 install pytest # content of test_sample.py def inc(x): return x + 1 def test_answer(): assert inc(3) == 5 pytest if __name__ == \u0026#39;__main__\u0026#39;: # 我是主模块身份 # 列举任意对象的全部属性 dir(obj) fabric awesome-python Selenium是一个用电脑模拟人操作浏览器网页 js2py纯python执行js supervisor-进程管理 numpy pandas PyGithub-封装github的api plotnine pillow xlwings操作excel flet-flutter的python包装 pydantic-类型注解加强版 anaconda-独立开源包管理器 Anaconda包括Conda、Python以及一大堆安装好的工具包,比如:numpy、pandas等 Miniconda包括Conda、Python conda是一个开源的包、环境管理器,可以用于在同一个机器上安装不同版本的软件包及其依赖,并能够在不同的环境之间切换\nDjango # settings.py LANGUAGE_CODE = \u0026#34;zh-hans\u0026#34; TIME_ZONE = \u0026#34;Asia/Shanghai\u0026#34; USE_TZ = False Flask requests Django-rest-framework scrapy falcon odoo以前openERP uvicorn-快如闪电的web框架 docker odoo frida vibora web3.py pycorrector-中文纠错 atomicwrites-原子写 sqlalchemy2.0-sql数据库 [deepcompare-深度比较] [jsonlines-jsonl文件] [boltons-常见第三方工具集合] fastapi-后起之秀http框架 sanic-最快的web框架 office-自动化系列 Pyodide-浏览器中运行python,采用webasm from atomicwrites import atomic_write with atomic_write(\u0026#39;foo.txt\u0026#39;, overwrite=True) as f: f.write(\u0026#39;Hello world.\u0026#39;) # \u0026#34;foo.txt\u0026#34; doesn\u0026#39;t exist yet. # Now it does. 特别包 # import cv2 pip3 install opencv-python pip3 install numpy # import PIL pip3 install pillow pip3 install image # No matching distribution found for onnxruntime # 暂时不支持m1芯片 pip3 install onnxruntime 浏览器本地文档 #更多命令 pydoc3 -help pydoc3 -p 7070 说明requirement.txt 通常我们会在项目的根目录下放置一个 requirement.txt 文件,用于记录所有依赖包和它的确切版本号。 每行一个依赖包,可以指定包的具体版本 tencentcloud-sdk-python=3.0.720 连接memcached pip3 install pymemcache #!python3 from pymemcache.client.base import Client client = Client(\u0026#39;localhost\u0026#39;) memKey = \u0026#39;/memcached\u0026#39; client.set(memKey, \u0026#39;\u0026lt;HTML\u0026gt;\u0026lt;H1\u0026gt;hello,world!\u0026lt;/H1\u0026gt;\u0026lt;/HTML\u0026gt;\u0026#39;) result = client.get(memKey) print(result) 连接redis pip3 install redis #!python3 import redis client = redis.Redis(host=\u0026#39;localhost\u0026#39;, port=6379, db=0) key = \u0026#34;python3Redis\u0026#34; client.set(key, \u0026#34;From Python3 Redis\u0026#34;) resp = client.get(key) print(resp) 今天这篇文章,聊一下python在web开发上的一些基础实现,阐述下自己理解中的WSGI、ASGI,以及拿uvicorn+FastAPI的组合举个ASGI应用的例子。\nWSGI-同步web应用\npython-web-app,也就是web应用层,实现WSGI接口,用作web请求的handler 用户向python-web-server发送web请求 python-web-server,又称作WSGI Server,解析请求数据,整理当前session的环境信息 python-web-server加载python-web-app,调用python-web-app实例的WSGI接口,处理请求 python-web-app处理完请求,返回结果给到python-web-server python-web-server写回返回结果,给回用户 def application(environ, start_response): start_response(\u0026#39;200 OK\u0026#39;, [(\u0026#39;Content-Type\u0026#39;, \u0026#39;text/plain\u0026#39;)]) return [b\u0026#39;Greetings universe\u0026#39;] ASGI-异步web应用\n一方面是支持asyncio的机制 另一方面也能够解决WSGI难以支持WebSocket之类长连接模式的问题 执行流程和wsgi差不多 async def application(scope, receive, send): event = await receive() ... await send({\u0026#34;type\u0026#34;: \u0026#34;websocket.send\u0026#34;, ...}) 百度开源Paddle 安装框架 python3 -m pip install paddlepaddle==2.3.1 -i https://mirror.baidu.com/pypi/simple 安装ocr pip3 install \u0026#34;paddleocr\u0026gt;=2.0.1\u0026#34; -i https://mirror.baidu.com/pypi/simple m1芯片特别安装\nDownload source code locally In requirements.txt, update to opencv-contrib-python==4.6.0.66 Pip install - r requirements.txt python setup.py install ppadleocr 安装在/opt/homebrew/opt/[email protected]/Frameworks/Python.framework/Versions/3.9/bin 第一次运行会下载训练好的模型到~/.paddleocr目录 ln -s /opt/homebrew/opt/[email protected]/Frameworks/Python.framework/Versions/3.9/bin/paddleocr paddleocr 安装paddleocrlabel\n[m1芯片源码安装]\n下载源码 git clone [email protected]:PaddlePaddle/PaddleOCR.git cd PPOCRLabel python setup.py install # 如果出现安装pyqt5失败,则采用brew install pyqt5 Installing PPOCRLabel script to /opt/homebrew/opt/[email protected]/Frameworks/Python.framework/Versions/3.9/bin cd /opt/homebrew/bin ln -s /opt/homebrew/opt/[email protected]/Frameworks/Python.framework/Versions/3.9/bin/PPOCRLabel PPOCRLabel # 运行,第一运行会下载必要东西~/.paddleocr目录 PPOCRLabel --lang ch # 针对特别业务,可以事先处理图片,再传入自动标注 # 直接下载whl文件,本地安装 pip3 install xxx.whl # applie m1 芯片安装,会有问题,因为没有直接aarch64.whl,需要重头编译,但目前没有办法成功 pip3 install pyqt5 # 幸好brew可以帮忙编译 brew install pyqt5 模型结构可视化VisualDL python3 -m pip install visualdl -i https://mirror.baidu.com/pypi/simple # Running VisualDL at http://localhost:8040/ (Press CTRL+C to quit) ./visualdl # 网络结构-静态,把模型文件拖进去\u0026lt;https://www.paddlepaddle.org.cn/inference/master/guides/export_model/visual_model.html\u0026gt; 另一个神经网络模型可视化-Netron wheel(轮子),wheel是一个zip压缩文件,将.whl扩展名替换为.zip wheel是python新的发行标准,旨在替代传统的egg,pip \u0026gt;=1.4的版本均支持wheel, 使用wheel作为你python库的发行文件,有如下好处:\n纯Python和本机C扩展软件包的安装速度更快 避免执行任意代码进行安装。 (避免setup.py)C扩展的安装不需要在Linux,Windows或macOS上进行编译 允许更好地缓存以进行测试和持续集成 在安装过程中创建.pyc文件,以确保它们与使用的Python解释器匹配跨平台和机器的安装更加一致 # 制作wheel安装包-方式1 python setup.py bdist_wheel # 制作wheel安装包-方式2 pip wheel --wheel-dir=/root/whl ./ 注解解释 在 Python 3.5 中,Python PEP 484 引入了类型注解(type hints)\n在 Python 3.6 中,PEP 526 又进一步引入了变量注解(Variable Annotations)。\n具体的变量注解语法可以归纳为两点:\n在声明变量时,变量的后面可以加一个冒号,后面再写上变量的类型,如 int、list 等等。 在声明方法返回值的时候,可以在方法的后面加一个箭头,后面加上返回值的类型,如 int、list 等等。 在PEP 8 中,具体的格式是这样规定的:\n在声明变量类型时,变量后方紧跟一个冒号,冒号后面跟一个空格,再跟上变量的类型。 在声明方法返回值的时候,箭头左边是方法定义,箭头右边是返回值的类型,箭头左右两边都要留有空格。 值得注意的是,这种类型和变量注解实际上只是一种类型提示,对运行实际上是没有影响的。\nopencv,python绑定 # OpenCV-Python接口中使用cv2.findContours ()函数来查找检测物体的轮廓。 contours, hierarchy = cv2.findContours (image,mode,method) # mask是与iamge一样大小的矩阵,其中的数值为0或者1,为1的地方,计算出image中所有元素的均值,为0 的地方,不计算 cv::Scalar mean = cv2.mean (image, mask) 应用cv2.warpPerspective()前需先使用cv2.getPerspectiveTransform()得到转换矩阵 cv2.warpPerspective() 叫做透视变换。 # 以彩色模式加载图片 img = cv2.imdecode(np_arr, cv2.IMREAD_COLOR) numpy 1、numpy.ones()函数 可以创建任意维度和元素个数的数组,其元素值均为1 2、使用语法 numpy.ones(shape, dtype=None, order=\u0026#39;C\u0026#39;) b = np.ones((3,4),dtype=np.int64) print(b) [[1 1 1 1] [1 1 1 1] [1 1 1 1]] paddleocr self.input_tensor.copy_from_cpu(norm_img_batch) self.predictor.run() outputs = [] for output_tensor in self.output_tensors: output = output_tensor.copy_to_cpu() outputs.append(output) if len(outputs) != 1: preds = outputs else: preds = outputs[0] Tensor 是 Paddle Inference 的数据组织形式,用于对底层数据进行封装并提供接口对数据进行操作,包括设置 Shape、数据、LoD 信息等。 注意: 应使用 Predictor 的 get_input_handle 和 get_output_handle 接口获取输入输出 Tensor "
},
{
"uri": "/redis/",
"title": "redis",
"tags": [],
"description": "",
"content": "安装运行 brew install redis brew services start redis wget https://download.redis.io/redis-stable.tar.gz tar -xzvf redis-stable.tar.gz cd redis-stable make # If the compile succeeds, you\u0026#39;ll find several Redis binaries in the src directory, including: # redis-server: the Redis Server itself # redis-cli is the command line interface utility to talk with Redis. # To install these binaries in /usr/local/bin, run: make install 自带客户端 #Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]] #Examples: # cat /etc/passwd | redis-cli -x set mypasswd # redis-cli get mypasswd # redis-cli -r 100 lpush mylist x # redis-cli -r 100 -i 1 info | grep used_memory_human: # redis-cli --quoted-input set \u0026#39;\u0026#34;null-\\x00-separated\u0026#34;\u0026#39; value # redis-cli --eval myscript.lua key1 key2 , arg1 arg2 arg3 # redis-cli --scan --pattern \u0026#39;*:12345*\u0026#39; #When no command is given, redis-cli starts in interactive mode #redis-cli的命令提示非常有帮助,比其他终端好用的多 redis-cli RedisInsight是Redis官方出品的可视化管理工具,可用于设计、开发、优化你的Redis应用 redis4引入自动内存碎片整理 # 开启自动内存碎片整理(总开关),默认no activedefrag yes # 当碎片达到 100mb 时,开启内存碎片整理 active-defrag-ignore-bytes 100mb # 当碎片超过 10% 时,开启内存碎片整理 active-defrag-threshold-lower 10 # 内存碎片超过 100%,则尽最大努力整理 active-defrag-threshold-upper 100 # 内存自动整理占用资源最小百分比 active-defrag-cycle-min 1 # 内存自动整理占用资源最大百分比 active-defrag-cycle-max 25 Notice:开启后,可能特定时间影响redis响应速度\nredis5带来了Stream Redis对消息队列(MQ,Message Queue)的完善实现 redis6增加了多线程 # io-threads 4 # Setting io-threads to 1 will just use the main thread as usual. # io-threads-do-reads no # Note that Gopher is not currently supported when \u0026#39;io-threads-do-reads\u0026#39; Redis实例占用相当大的CPU耗时的时候才建议采用,否则使用多线程没有意义。基本上我们都是观众!!!\n常用功能 功能 命令 备注 String set,get,setnx,mget,mset,msetnx 最大512MB,可存任何数据 List lpush,lpop,rpush,rpop,blpop,brpop,llen,lpushx,lrem,lrange 超过40亿个元素 Hash hget,hset,hdel,hgetall,hkeys,hvals,hlen,hmset,hmget 超过40亿个元素 Set sadd,spop,srem,scard,smembers,sismember,sdiff,sinter,sunion 超过40亿个成员 SortedSet zadd,zrem,zcard,zcount,zscore,zrange 超过40亿个成员 Pub/Sub subscribe,publish,unsubscribe 消息不会保存,广播型 Stream xadd,xdel,xlen,xread,xgroup,xreadgroup,xinfo,xtrim 消息会保存,每个消息都是一组键值对,同组竞争,组间广播 Key del,keys,type,object,ttl,persist,randomkey,rename 针对键操作 Pipelining 优点:减少RTT(往返时间),多次网络IO,系统调用的消耗 缺点:独占链接,占用redis内存缓存命令结果 Auth auth password 验证密码 HyperLogLog pfadd,pfcount 基数估计 xreadgroup和xack配合使用 WHILE true entries = XREADGROUP $GroupName $ConsumerName BLOCK 2000 COUNT 10 STREAMS mystream \u0026gt; if entries == nil puts \u0026#34;Timeout... try again\u0026#34; CONTINUE end FOREACH entries AS stream_entries FOREACH stream_entries as message process_message(message.id,message.fields) # ACK the message as processed XACK mystream $GroupName message.id END END END 常见问题 缓存雪崩:短时间内大量键超时失效\n缓存击穿:缓存中没有键值\n确实不存在:用布隆过滤器优化 键超时:设置永不超时,受最大内存限制 批量删除 --批量删除msg开始的键值 EVAL \u0026#34;return redis.call(\u0026#39;del\u0026#39;, unpack(redis.call(\u0026#39;keys\u0026#39;, ARGV[1])))\u0026#34; 0 \u0026#39;msg*\u0026#39; redis通讯协议-RESP 请求协议 *后面数量表示存在几个$ $后面数量表示字符串的长度 每项用\\r\\n分隔 *3\\r\\n$3\\r\\nSET\\r\\n$5\\r\\nmykey\\r\\n$7\\r\\nmyvalue\\r\\n pipeline实现就是连接发送命令,不用每个都等\n"
},
{
"uri": "/other/rpc/",
"title": "rpc",
"tags": [],
"description": "",
"content": "运行过程 sequenceDiagram actor c as Client actor cs as ClientSub actor s as Server actor ss as ServerSub actor h as Handler c-\u003e\u003ecs: 函数调用 cs-\u003e\u003ecs: json/protobuf等序列化 cs-\u003e\u003es: tcp/http等发送 s-\u003e\u003ess: 函数调用 ss-\u003e\u003ess: json/protobuf等反序列化 ss-\u003e\u003eh: 功能实现 h--\u003e\u003ess: 函数返回 ss--\u003e\u003ess: json/protobuf等序列化 ss--\u003e\u003es: 回包 s--\u003e\u003ecs: tcp/http等发送 cs--\u003e\u003ecs: json/protobuf等反序列化 cs--\u003e\u003ec: 函数返回 常见框架 grpcurl 类似curl,但用于grpc\n"
},
{
"uri": "/nginx/rtmp/",
"title": "rtmp",
"tags": [],
"description": "",
"content": "下载安装rtmp模块 编译 /configure --prefix=/Users/Shared/nginx \\ --add-module=../nginx-party-module/nginx-rtmp-module \\ --with-http_ssl_module \\ --with-openssl=/opt/homebrew/Cellar/[email protected]/1.1.1m\\ --with-debug make make install 修改配置 rtmp { server { listen 1935; application vod { play /Users/xxx/iCloud-archive/video; } } } 访问 #vlc打开串流地址 rtmp://host/vod/xxx.mp4 附录 RTMP、RTSP、HTTP协议理论上都可以用来做视频直播或点播,直播一般用RTMP,RTSP,点播用 HTTP\nRTMP协议\n是流媒体协议。 RTMP协议是 Adobe 的私有协议,未完全公开。 RTMP协议一般传输的是 flv,f4v 格式流。 RTMP一般在 TCP 1个通道上传输命令和数据。 RTSP协议\n是流媒体协议。 RTSP协议是共有协议,并有专门机构做维护 RTSP协议一般传输的是 ts、mp4 格式的流。 RTSP传输一般需要 2-3 个通道,命令和数据通道分离。 HTTP协议\n不是是流媒体协议。 HTTP协议是共有协议,并有专门机构做维护 HTTP协议没有特定的传输流 HTTP传输一般需要 2-3 个通道,命令和数据通道分离 "
},
{
"uri": "/other/rust/",
"title": "Rust",
"tags": [],
"description": "",
"content": " 官网 Rustup metadata and toolchains will be installed into the Rustup home directory, located at: $HOME/.rustup This can be modified with the RUSTUP_HOME environment variable. The Cargo home directory located at: $HOME/.cargo This can be modified with the CARGO_HOME environment variable. The cargo, rustc, rustup and other commands will be added to Cargo s bin directory, located at: $HOME/.cargo/bin This path will then be added to your PATH environment variable by modifying the profile files located at: $HOME/.profile $HOME/.bashrc $HOME/.zshenv You can uninstall at any time with rustup self uninstall and these changes will be reverted. 中文官网\nrocket-web框架\n小知识\n升级rust及相关工具链 rustup update 本地查看文档 rustup doc 每隔一段时间就发布一个版次,主要有2015,2018,2021,主程序和库代码可以依赖不同版次的. 强大的rust的web框架\n"
},
{
"uri": "/golang/shell/",
"title": "shell",
"tags": [],
"description": "",
"content": "编译常用示例 #! /bin/bash target=local set -x #回显执行命令 GOPATH=$(go env GOPATH) GITVERSION=$(git describe --tags --always) GITBRANCH=$(git symbolic-ref -q --short HEAD) DATETIME=$(date \u0026#34;+%Y-%m-%d_%H:%M:%S\u0026#34;) HOSTNAME=$(hostname) golangci-lint run --timeout=1h revive -formatter friendly ./... rm -rf ${target}* go build -o ${target} -ldflags \u0026#34;-w -s -X main.GitHash=${GITVERSION}-${GITBRANCH} -X main.CompileTime=${DATETIME} -X main.HostName=${HOSTNAME}\u0026#34; . ./${target} "
},
{
"uri": "/other/shell/",
"title": "shell",
"tags": [],
"description": "",
"content": "升级替换系统命令-modern-unix) bat代替cat, bat 相比 cat 增加了行号和颜色高亮 👍 duf代替df exa代替ls dust代替du procs代替ps difft替代diff McFly(https://github.com/cantino/mcfly) zoxide代替cd,可能不用启动z tldr替代man, tldr-github pip install tldr ctrl+r 搜索历史命令 # 或者ctrl+r mcfly search 并发启动命令 for var in {0..2} do #用{}把循环体括起来,后加一个\u0026amp;符号,代表每次循环都把命令放入后台运行 #一旦放入后台,就意味着{}里面的命令交给操作系统的一个线程处理了 { echo ${var} }\u0026amp; done wait #wait命令的意思是,等待(wait命令)上面的命令(放入后台的)都执行完毕了再往下执行 常用源目录 /etc/yum.repos.d systemd新时代linux服务管理软件,就是平时使用(systemctl start stop enable disable status) xxx systemd是一个服务管理器,它使管理服务器变得更加容易。 对于支持 systemd 的软件,安装的时候,它会自动的在 /usr/lib/systemd/system 目录添加一个配置文件 /lib -\u0026gt; /usr/lib 通常路径被软链接 curl带用户名密码的pos提交 curl -i -X POST \\ http://localhost:4080/api/test/_doc \\ -u user:pwd \\ -H \u0026#39;Content-Type: application/json\u0026#39; \\ -d \u0026#39;{\u0026#34;name\u0026#34;:\u0026#34;中文12344\u0026#34;, \u0026#34;value\u0026#34;:\u0026#34;https://abc.iste/\u0026#34;}\u0026#39; curl -X DELETE \\ http://127.0.0.1:4080/api/index/xxx/ \\ -u user:pwd # 获取本机外网ip curl ifconfig.me 查看哪个命令在哪个包中 # dnf是yum的继承者,更好用 # 查找提供指定内容的软件包 dnf provides \u0026#39;*/chsh\u0026#39; # 以 Fedora 为基准的安装包如下 dnf install -y util-linux-user # 搜索一定要加引号 dnf search \u0026#39;keyword\u0026#39; # 修改默认的shell chsh [option] user # 带调试查看ssh登陆过程,用于卡 ssh -vvv xxxx # 后来ssh -v 登录查看了下日志,发现一直卡在debug1: SSH2_MSG_KEXINIT sent。直到最后链接失败。 # 网上查了很多,发现是因为mtu设置的数值太大。网络-\u0026gt;高级-\u0026gt;手动(平时是自动)-\u0026gt;指定1500 .ssh/config管理多个ssh密钥 ~/.ssh/config如果不存在,则创建.\n... # Host可以自定义 Host github2 # github.com这个是真实远程服务器,不能修改 # id_ecdsa.pub内容要在github相应帐户添加为ssh密钥 HostName github.com PreferredAuthentications publickey # 指明用哪个文件 IdentityFile ~/.ssh/id_ecdsa ... Host的定义可以有多组,用指定哪个ssh密钥对应哪个HostName/Host 一般不同域名不同ssh密钥不用配置config,能自动查找对应 测试config\n#github2为config文件中的Host值 ssh -T git@github2 # 查看ssh登陆详情 ssh -vvvT git@github2 如果github.com的帐户username设置了id_ecdsa.pub 则会回包Hi username! You\u0026rsquo;ve successfully authenticated, but GitHub does not provide shell access 修改远程仓库url\n#[email protected]:username/reposname.git==\u0026gt;git@github2:username/reposname.git #github2为config文件中的Host值,表明reposname要采用id_ecdsa密钥 git clone git@github2:username/reposname.git 本地reposename配置.git/config\ncd reposname git config user.name \u0026#39;username\u0026#39; git config user.email \u0026#39;[email protected]\u0026#39; github根据配置文件的user.email来获取github帐号显示author信息 在连接远程SSH服务的时候,经常会发生长时间后的断线,或者无响应(无法再键盘输入) 客户端定时发送心跳,添加修改本机~/ssh/config vim config # 即每隔30秒,向服务器发出一次心跳 ServerAliveInterval 30 # 若超过100次请求,都没有发送成功,则会主动断开与服务器端的连接。 ServerAliveCountMax 100 服务器端定时向客户端发送心跳,修改服务器端 ssh配置 /etc/ssh/sshd_config vim /etc/ssh/sshd_config # 表示每隔多少秒,服务器端向客户端发送心跳 ClientAliveInterval 30 # 表示上述多少次心跳无响应之后,会认为Client已经断开 ClientAliveCountMax 6 xargs(命令行参数)和|(标准输入) #find标准输出为每行一个文件名 #直接通过管道转为grep的标准输入,则grep搜索标准输入包括protobuf的 #输出结果:文件名以.mod结束且包括protobuf find . -name \u0026#34;*.mod\u0026#34; | grep protobuf #管道转为xargs的标准输入, #xargs把标准输入转化为grep的参数 #grep指定的文件名里内容包括protobuf的 #输出结果:文件名以.mod结束且文件内容包括protobuf find . -name \u0026#34;*.mod\u0026#34; | xargs grep protobuf # 搜索名字叫html目录 find . -type d -name \u0026#39;html\u0026#39; 管道(|)的作用是将前面命令的标准输出作为后面命令的标准输入 xargs将标准输入转成各种格式化的参数 常用命令 set -v 回显命令,但不替换变量值 set -x 回显命名,替换变量值 # 用双引号处理带空格的文件 cp \u0026#34;带空格的文件\u0026#34; newfile ls -l | grep \u0026#34;^-\u0026#34; | wc -l 当前目录下文件总数 # linux网络共享网盘nfs,/etc/exports文件增加一个共享目录 #产生ssh密钥对,注意-C大写,保存id_rsa文件名,ssh会默认读取,否则就要明确指出 #-b:指定密钥长度;-C:添加注释;-f:指定用来保存密钥的文件名;-t:指定要创建的密钥类型。 #现在很多地方都不支持rsa,建议采用ed25519/ecdsa # -t [dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa] ssh-keygen -t rsa -C \u0026#34;[email protected]\u0026#34; -f id_rsa # 注意-t之后的空格,有可能提示不识别参数 ssh-keygen -t ed25519 -C \u0026#34;[email protected]\u0026#34; -f id_ed25519 # 显示正在使用的shell echo $SHELL # 快速切换目录, vim .bashrc/.zshrc source .bashrc/.zshrc export $CDPATH=.:~:/xxx/ #获取历史命令 #zsh cat $HOME/.zsh_history #bsh cat $HOME/.bash_history # 查看磁盘占用情况 df -h #查看当前一级目录文件大小 du -h --max-depth=1 # 清空./var/journalctl日志 journalctl --vacuum-size=10M # ls人性化阅读 ls -lh # 复制到粘贴板 #windows clip \u0026lt; ~/.ssh/id_ed25519.pub #mac pbcopy \u0026lt; ~/.ssh/id_ed25519.pub #linux xclip -sel clip \u0026lt; ~/.ssh/id_ed25519.pub # 获取脚本所在目录 dirname $0 cd `dirname $0` pwd # 获取home目录 echo $HOME # 当前时间、系统已经运行了多长时间、目前有多少登陆用户、系统在过去的1分钟、5分钟和15分钟内的平均负载。 uptime # 解决ssh超级慢(去除服务端利用dns反查客户端) vi /etc/ssh/sshd_config UseDNS no GSSAPIAuthentication no # 列出所有监听tcp端口程序 netstat -ltpn #查看所有服务监听端口 netstat -a # 监听tcp指定端口 tcpdump tcp port xxx #查看网卡流量:每1秒 显示 1次 显示 10次 sar -n DEV 1 10 # 查看命令执行情况 set -V #防火墙: #查看是否打开端口: firewall-cmd --list-all #添加端口: firewall-cmd --permanent --add-port=3000/tcp #批量增加端口: firewall-cmd --permanent --zone=public --add-port=7000-8000/tcp #移除端口: firewall-cmd --permanent --remove-port=7780/tcp #重新加载规则生效 firewall-cmd --reload #查找前20名占用内存较大: ps aux | head -1;ps aux |grep -v PID |sort -rn -k +4 | head -20 # 建立软连接 ln -s 真实存在目录 软链接 积累 # 使用-j参数 不处理压缩文件中原来目录路径 zip -qj file.zip /xxx/xx/xx 示例脚本 linux 普通用户实现sudo免密 vim /etc/sudoers.d 增加一个文件,添加以下内容 username ALL=(ALL) NOPASSWD:ALL 利用git部署更新脚本 #!/usr/bin/env bash cd ${gitdir} # 批量杀死监控进程 shell脚本或专用管理程序 ps -ef|grep xxx | grep -v grep | awk \u0026#39;{print $2}\u0026#39; | xargs kill -9 # 批量杀死目标进程 ps -ef|grep yyy | grep -v grep | awk \u0026#39;{print $2}\u0026#39; | xargs kill -9 # 拉取最新程序 git pull # 跑起监控进程 nohup ./xxx.sh \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 \u0026amp; 监控脚本 #!/usr/bin/env bash while true do # 查看目标进程还在不在 procnum=` ps -ef|grep \u0026#34;yyy$\u0026#34;|grep -v grep|wc -l` if [ $procnum -eq 0 ]; then cd ${basedir} nohup ./yyy \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 \u0026amp; fi # 延时30秒 sleep 30 done 编译脚本 #!/usr/bin/env bash # 批量杀死目标进程 ps -ef|grep yyy | grep -v grep | awk \u0026#39;{print $2}\u0026#39; | xargs kill -9 hash=`git rev-parse --short HEAD` rc=`date \u0026#34;+%Y-%m-%d_%H:%M:%S\u0026#34;` target=yyy go build -ldflags \u0026#34;-s -w -X main.GitHash=${hash} -X main.CompileTime=${rc}\u0026#34; -tags=jsoniter -o ${target} ${target}.go chmod a+x ${target} rundir=${target}_run rm -rf ${rundir} mkdir ${rundir} mv ${target} ${rundir} cp -r conf ${rundir}/ nohup ./${target} \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 \u0026amp; exit 设置北京时间 sudo timedatectl set-timezone Asia/Shanghai 常见包管理 apt = apt-get、apt-cache 和 apt-config 中最常用命令选项的集合。 dnf 是 yum的升级版 显卡 sudo lshw -numeric -C display显示显卡信息,lspci | grep -i vga 权限错误 # Permissions 0644 for \u0026#39;/root/.ssh/id_ecdsa\u0026#39; are too open # 降低权限 chmod 0600 ~/.ssh/id_ecdsa "
},
{
"uri": "/golang/sort/",
"title": "sort包",
"tags": [],
"description": "",
"content": " classDiagram Interface \u003c|-- IntSlice : 实现 Interface \u003c|-- Float64Slice : 实现 Interface \u003c|-- StringSlice : 实现 class Interface{ +Len() int +Less(i, j int) bool +Swap(i, j int) } classDiagram Interface \u003c|.. Sort : 依赖 Sort \u003c|-- Ints : []int Sort \u003c|-- Float64s : []float64 Sort \u003c|-- Strings : []string Sort \u003c|-- Slice : []其他类型 classDiagram Search \u003c|-- SearchInts : []int Search \u003c|-- SearchFloat64s : []float64 Search \u003c|-- SearchStrings : []string type Interface interface { Len() int Less(i, j int) bool Swap(i, j int) } // 采用快排/堆排/插排组合 func Sort(data Interface) func Ints(x []int) func Float64s(x []float64) func Strings(x []string) //采用反射自动实现Swap(i, j int) func Slice(x any, less func(i, j int) bool) // 稳排采用分段插排+合并组合 func Stable(data Interface) func SliceStable(x any, less func(i, j int) bool) // 二分搜索有序序列 func Search(n int, f func(int) bool) int func SearchInts(a []int, x int) int func SearchFloat64s(a []float64, x float64) int func SearchStrings(a []string, x string) int "
},
{
"uri": "/golang/stringer/",
"title": "stringer",
"tags": [],
"description": "",
"content": "官方自动生成string main.go内容 //go:generate stringer -type=Pill type Pill int const ( Placebo Pill = iota Aspirin Ibuprofen Paracetamol Acetaminophen = Paracetamol ) 执行命令 go generate 生成的pill_string.go内容 import \u0026#34;strconv\u0026#34; // 这段防止generate之后,修改后没有再次generate,通过编译错误强制提示 func _() { // An \u0026#34;invalid array index\u0026#34; compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. var x [1]struct{} _ = x[Placebo-0] _ = x[Aspirin-1] _ = x[Ibuprofen-2] _ = x[Paracetamol-3] } const _Pill_name = \u0026#34;PlaceboAspirinIbuprofenParacetamol\u0026#34; var _Pill_index = [...]uint8{0, 7, 14, 23, 34} func (i Pill) String() string { if i \u0026lt; 0 || i \u0026gt;= Pill(len(_Pill_index)-1) { return \u0026#34;Pill(\u0026#34; + strconv.FormatInt(int64(i), 10) + \u0026#34;)\u0026#34; } return _Pill_name[_Pill_index[i]:_Pill_index[i+1]] } "
},
{
"uri": "/other/svn/",
"title": "svn",
"tags": [],
"description": "",
"content": "svn命令 下载 svn checkout svn://host/svn/IOS/remote_dir (svn项目全路径)project_dir(本地目录全路径) --username 用户名 --password 密码 svn checkout 简写:svn co\n添加新文件 svn add file(文件名) svn add *.php(添加当前目录下所有的php文件) 提交到版本库 svn commit -m \u0026#34;LogMessage\u0026#34; PATH svn commit -m “提交当前目录下的全部在版本控制下的文件“ * ( *表示全部文件 ) svn commit 简写:svn ci\n更新文件 svn update svn update 文件名 提交的时候提示过期冲突,需要先 update 修改文件\n然后清除svn resolved,最后再提交commit。\nsvn update 间写: svn up\n查看文件或者目录状态 svn status [-v] path(目录下的文件和子目录的状态,正常状态不显示) ?:不在svn的控制中;\nM:内容被修改;\nC:发生冲突;\nA:预定加入到版本库;\nK:被锁定\nD:文件、目录或是符号链item预定从版本库中删除。\nI:忽略\nsvn status 简写:svn st\n查看日志(显示文件的所有修改记录,及其版本号的变化) # 查看最近3条日志 svn log [path] -l 3 解决冲突 # 手工解决冲突后,移除工作副本的目录或文件的“冲突”状态,再提交 svn resolved PATH 删除文件 # 本地先删,再提交 svn delete test.php svn ci -m \u0026#39;delete test file‘ 恢复本地修改 # 用法: revert PATH... svn revert: 恢复原始未改变的工作副本文件 (恢复大部份的本地修改)。 注意: 本子命令不会存取网络,并且会解除冲突的状况。但是它不会恢复被删除的目录\n# 丢弃对一个文件的修改 svn revert foo.c # 恢复一整个目录的文件,. 为当前目录 svn revert --recursive . 版本库下的文件和目录列表 svn list [path] 忽略目录 # 注意没有目录斜杠 svn propset svn:ignore .idea . 查看文件详细信息 # svn info path svn info test.php 比较差异 # svn diff path(将修改的文件与基础版本比较) svn diff test.php # svn diff -r m:n path(对版本m和版本n比较差异) svn diff -r 200:201 test.php svn diff 简写:svn di\nSVN 帮助 svn help 全部功能选项 svn help ci 具体功能的说明 上传 svn import project_dir(本地项目全路径) http://host/svn/IOS/Ben/remote_dir(svn项目全路径) -m \u0026#34;必填, 不填此命令执行不会成功.\u0026#34; 服务器上remote_dir若不存在, 会自动创建;\n只会上传project_dir目录下的文件到remote_dir的目录下\nimport之后, project_dir并没有自动转化为工作目录, 需要重新checkout(后面会用到)\n"
},
{
"uri": "/tags/",
"title": "Tags",
"tags": [],
"description": "",
"content": ""
},
{
"uri": "/other/tesseract/",
"title": "tesseract",
"tags": [],
"description": "",
"content": "安装 # 多半已安装过了,最新版本为5.xx brew install tesseract # This formula contains only the \u0026#34;eng\u0026#34;, \u0026#34;osd\u0026#34;, and \u0026#34;snum\u0026#34; language data files. # If you need any other supported languages, run `brew install tesseract-lang` # 本质是下载github所有训练完好的模型数据,放在/opt/homebrew/share/tessdata,供tesseract调用 brew install tesseract-lang 使用 # 获取帮助 tesseract --help-extra # 告诉tesseract 源文件chinese.png -l 表示中文 stdout输出到标准库 tesseract chinese.png stdout -l chi_sim # 类似数字识别 tesseract digit.png stdout -l snum # 类似英文识别 tesseract english.png stdout -l eng # 单行文本识别率非常不错,多行错误率非常高 "
},
{
"uri": "/other/unity/",
"title": "unity",
"tags": [],
"description": "",
"content": "清除启动界面工程 cd /Users/\u0026lt;yourUserName\u0026gt;/Library/Preferences/ cat com.unity3d.UnityEditor5.x.plist defaults read com.unity3d.UnityEditor5.x.plist defaults delete com.unity3d.UnityEditor5.x \u0026#34;RecentlyUsedProjectPaths-0\u0026#34; 打印调用堆栈 string trackStr = new System.Diagnostics.StackTrace().ToString(); Debug.Log (\u0026#34;Stack Info:\u0026#34; + trackStr); 积累 Unity是单线程设计的游戏引擎,子线程中无法运行Unity SDK Unity主循环是单线程,游戏脚本MonoBehavior有着严格的生命周期 倾向使用time slicing(时间分片)的协程(coroutine)去完成异步任务 组件图 常见热更方案 利用c#反射,动态加载程序集,实现代码更新 // 从指定网址下载 Assembly assembly = Assembly.LoadFile(assemblyFile); 创建Lua虚拟机,动态加载Lua脚本 腾讯-xLua方案\nXLua.LuaEnv luaenv = new XLua.LuaEnv(); luaenv.DoString(\u0026#34;CS.UnityEngine.Debug.Log(\u0026#39;hello world\u0026#39;)\u0026#34;); luaenv.Dispose(); tolua-号称最快\nLuaState lua = new LuaState(); lua.Start(); lua.DoString(\u0026#34;print(\u0026#39;hello world\u0026#39;)\u0026#34;); lua.Dispose(); "
},
{
"uri": "/other/vim/",
"title": "vim",
"tags": [],
"description": "",
"content": "常用命令 ddp-交换上下行-光标在上行,其与下行交换 :$ 跳转到最后一行 :1 跳转到第一行 查找字符串 /hello 查找光标处下一个\u0026quot;hellp\u0026quot; ,键入\u0026quot;n\u0026quot; 继续查找下一个,键入\u0026quot;shift+n\u0026quot;(大写N), 向上查找 ?hello朝找光标处上一个\u0026quot;hellp\u0026quot; 键入\u0026quot;n\u0026quot; 继续查找上一个, 键入\u0026quot;shift+n\u0026quot;(大写N), 向下查找 /\u0026lt;printf\u0026gt; 精确搜索printf:\u0026quot;\u0026lt;“表示匹配单词开头,”\u0026gt;“表示匹配单词末尾,需要加转义符\u0026quot;\u0026quot; 复制粘贴 复制一行,我们只要把光标移动到想复制的那一行,按yy,就是两次y键, 粘贴,把光标移动到你想粘贴的那一行,按p键即可。 复制多行,把光标移动到想复制多行的开头,想要向下复制几行,就按nyy,比如我想从这一行开始复制5行,就按5yy 插件管理器-vim-plug vim-plug 是 vim 下的插件管理器, 可以帮我们统一管理后续的所有插件, 后续的安装插件全部由此工具完成 类似的插件管理工具还有 Vundle, 相较而言 vim-plug 支持异步且效率非常高, 具体选择交由读者自己\n安装\ncurl -fLo ~/.vim/autoload/plug.vim --create-dirs \\ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim 配置声明 vim .vimrc :set term=builtin_ansi :set encoding=utf-8 :set nocompatible :set nu :set hlsearch :syn on call plug#begin() Plug \u0026#39;preservim/nerdtree\u0026#39; Plug \u0026#39;jiangmiao/auto-pairs\u0026#39; Plug \u0026#39;vim-airline/vim-airline\u0026#39; Plug \u0026#39;vim-airline/vim-airline-themes\u0026#39; Plug \u0026#39;morhetz/gruvbox\u0026#39; Plug \u0026#39;frazrepo/vim-rainbow\u0026#39; Plug \u0026#39;chiel92/vim-autoformat\u0026#39; Plug \u0026#39;vim-scripts/bash-support.vim\u0026#39; Plug \u0026#39;zaach/jsonlint\u0026#39; Plug \u0026#39;plasticboy/vim-markdown\u0026#39; Plug \u0026#39;ambv/black\u0026#39; Plug \u0026#39;fatih/vim-go\u0026#39; Plug \u0026#39;sheerun/vim-polyglot\u0026#39; call plug#end() 激活安装-相应插件 $ vim #打开vim :PlugStatus #查看插件状态 :PlugInstall #安装之前在配置文件中声明的插件 优秀插件网站(https://github.com/vim-awesome/vim-awesome) 机器上/.vimrc 修改无法显示中文及方向键不能移动光标 :set term=builtin_ansi :set encoding=utf-8 :set nocompatible 修改~/.bashrc 打开force_color_prompt=yes 右键不能复制 vim set mouse-=a屏蔽了鼠标右健功能. "
},
{
"uri": "/other/wasm/",
"title": "wasm",
"tags": [],
"description": "",
"content": "官方网站 WebAssembly,通常简称为 Wasm,是一种相对较新的技术,它允许你编译用 40 多种语言(包括 Rust、C、C++、JavaScript 和 Golang)编写的应用程序代码,并在沙盒环境中运行它。最初的用例主要是在 Web 浏览器中运行本地代码,但是由于 WebAssembly 系统接口(WASI)的存在,Wasm 正在迅速向浏览器之外扩展,\nwasmedge wasm-二进制标准格式,另一个\u0026quot;一次编译,到处执行\u0026quot; "
},
{
"uri": "/other/web/",
"title": "web",
"tags": [],
"description": "",
"content": "HTTP协议 flowchart LR v1(HTTP1.1-1999年) --分帧复用--\u003e v2(HTTP2-2015年) v2 --tcp转向udp--\u003ev3(HTTP3-2021年) HTTP不变的协议过程 HTTP底层传输变化 HTTP1.1改进\n默认持久连接 增加Cookie,虚拟主机,动态内容支持 使用CDN的实现域名分片机制 HTTP1.1问题\nTCP的慢启动 多条TCP连接竞争带宽 队头阻塞 HTTP2改进\n二进制分帧层 请求的优先级 服务器推送 头部压缩 HTTP2问题\n有序字节流引出的队头阻塞(Head-of-line blocking),使得HTTP2的多路复用能力大打折扣 TCP与TLS叠加了握手时延,建链时长还有1倍的下降空间 基于TCP四元组确定一个连接,这种诞生于有线网络的设计,并不适合移动状态下的无线网络,这意味着IP地址的频繁变动会导致TCP连接、TLS会话反复握手,成本高昂。 HTTP3改进\nHTTP3基于UDP协议重新定义了连接,在QUIC层实现了无序、并发字节流的传输,解决了队头阻塞问题 HTTP3重新定义了TLS协议加密QUIC头部的方式,既提高了网络攻击成本,又降低了建立连接的速度 HTTP3 将Packet、QUIC Frame、HTTP3 Frame分离,实现了连接迁移功能,降低了5G环境下高速移动设备的连接维护成本 jwt(JSON Web Token) 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。\n服务器采用秘钥签名检验token内部数据是否正确,不再保存session\n传统session方案,占用内存,不易扩展\nsequenceDiagram actor u as 用户 actor s as 服务器 u-\u003e\u003es: login登陆 s--\u003e\u003eu: form填写用户名密码 u-\u003e\u003es: Post用户名密码 s-\u003e\u003es: 数据库检查,生成并保存session s--\u003e\u003eu: setcookie sessionID u-\u003e\u003es: cookies带上sessionID s-\u003e\u003es: 根据sessionID,获取session s--\u003e\u003eu: 提供服务 jwt方案,服务器私用secret,除过期时间之外,token不易作废 sequenceDiagram actor u as 用户 actor s as 服务器 u-\u003e\u003es: login登陆 s--\u003e\u003eu: form填写用户名密码 u-\u003e\u003es: Post用户名密码 s-\u003e\u003es: 数据库检查,利用secret生成token s--\u003e\u003eu: Authorization token u-\u003e\u003es: Authorization token s-\u003e\u003es: 根据secret,检验token s--\u003e\u003eu: 提供服务 jwt-token构成 flowchart LR subgraph Header h(json对象base64编码) end subgraph Payload p(json对象base64编码) end subgraph Signature s(加密计算后base64编码) end Header--用点号.连接--\u003ePayload--用点号.连接--\u003eSignature Header示例 { \u0026#34;alg\u0026#34;: \u0026#34;HS256\u0026#34;, \u0026#34;typ\u0026#34;: \u0026#34;JWT\u0026#34; } Payload示例 { \u0026#34;sub\u0026#34;: \u0026#34;1234567890\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;John Doe\u0026#34;, \u0026#34;admin\u0026#34;: true } Signature HMACSHA256( base64UrlEncode(header) + \u0026#34;.\u0026#34; + base64UrlEncode(payload), secret) 实例展示 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ\n系统容错 限流-熔断-降级 限流,当核心服务的处理能力不能应对外部请求的突增流量时,必须采取限流的措施。\n熔断,非核心服务\nsequenceDiagram actor u as 用户 actor l as 断路器 actor s as 服务 u-\u003e\u003el: 请求 l-\u003e\u003es: 转发请求 s--\u003e\u003el: 成功回包 l--\u003e\u003eu: 转发成功回包 u-\u003e\u003el: 请求 l-\u003e\u003es: 转发请求 s--\u003e\u003el: 失败 l-\u003e\u003el: 累计失败,达到阀值 l--\u003e\u003eu: 转发失败 u-\u003e\u003el: 请求 l-\u003e\u003el: 检查服务恢复? l--\u003e\u003eu: 回包失败 服务熔断是指调用方访问服务时通过断路器做代理进行访问,断路器会持续观察服务返回的成功、失败的状态,当失败超过设置的阈值时断路器打开,请求就不能真正地访问到服务了。 CLOSED:默认状态。断路器观察到请求失败比例没有达到阈值,断路器认为被代理服务状态良好。 OPEN:断路器观察到请求失败比例已经达到阈值,断路器认为被代理服务故障,打开开关,请求不再到达被代理的服务,而是快速失败。 HALF OPEN:断路器打开后,为了能自动恢复对被代理服务的访问,会切换到半开放状态,去尝试请求被代理服务以查看服务是否已经故障恢复。如果成功,会转成CLOSED状态,否则转到OPEN状态 降级-采用预设方案行动,针对非核心,非必要服务\nwebdav WebDAV (Web-based Distributed Authoring and Versioning) 一种基于 HTTP 1.1协议的通信协议。 它扩展了HTTP 1.1,在GET、POST、HEAD等几个HTTP标准方法以外添加了一些新的方法, 使应用程序可对Web Server直接读写,并支持写文件锁定(Locking)及解锁(Unlock),还可以支持文件的版本控制。 jsonnet brew install jsonnet 优化方向 浏览器处理缓存,如下图所示 webpack打包\n图片换格式WebP\n浏览器处理HTML\n优秀网站 nodejs-前端必备\nBun-更快更现化的nodejs\nvue3-最火的前端框架\necharts-必备图库\napisix-api管理\napache-大量优秀项目\nnginx-官网\nnginx-开源社区\nopenresty\nkong-网关\nBizCharts-图形库\ng2-图形库\nangular\ndart, pub-库集散地,绝对值得多看看\njavascript-英文学习站\njavascript-w3c\n前端cdn\nmermaidjs-代码画图库\nplantuml-代码画图库\n团队文档-阿里出品语雀\nConfluence-团队文档,据说现在不能私有部署\n"
},
{
"uri": "/other/windows/",
"title": "windows",
"tags": [],
"description": "",
"content": " win10运行linux命令\n系统设置——更新和安全——针对开发人员——选择开发者模式 搜索“程序和功能”,选择“开启或关闭Windows功能”,开启Windows Subsystem for Linux (Beta),并重启系统 下载安装linux 配置windows Terminal\n让终端更优雅 windows版-brew fig-更好体验 windows版-brew2 mingw-windows 小知识\npower shell # 十六进制显示文件 Format-Hex -Path ./fileName.xxx # 文件浏览器打开当前目录 explorer . "
},
{
"uri": "/other/wireshark/",
"title": "wireshark",
"tags": [],
"description": "",
"content": "抓https,http2包 配置firefox #设置环境变量,让firefox编入通讯密钥,调试完成后记得删除这个环境变量,它会影响速度和浪费空间 export SSLKEYLOGFILE=~/sslkeylog.log #命令行启动,让firefox继承环境变量,也防止firefox后台运行,没有真正重启 /Applications/Firefox.app/Contents/MacOS/firefox-bin 配置wireshark\n设置通讯密钥文件位置 设置显示域名,默认显ip firefox访问网址,wireshark抓包 显示过滤语法 # 获取指定port包 tcp.port == 8411 tcp.port in {80, 443, 8080} # 指定ip源或目的 ip.src == 192.168.0.1 ip.dst == 192.168.0.1 # 按长度 http.content_length \u0026lt;=20 udp.length \u0026lt; 30 # 按协议 http http contains \u0026#34;https://www.wireshark.org\u0026#34; http.request.method == \u0026#34;POST\u0026#34; http.request.method in {\u0026#34;HEAD\u0026#34;, \u0026#34;GET\u0026#34;} # 条件组合 and or ip.src == 192.168.0.1 or ip.dst == 192.168.0.1 ip.dst eq www.mit.edu capture过滤语法 表达式规则 [not] primitive [and|or [not] primitive ...] primitive有几种形式\n[src|dst] host ether [src|dst] host gateway host [src|dst] net [{mask }|{len }] [tcp|udp] [src|dst] port less|greater ip|ether proto relop 示例\ntcp port 23 and not src host 10.0.0.5 小知识 局域网抓包可采用路由器镜像端口 远程服务器抓包,远程抓包+rpcap,本机wireshark连接远程rpcap,则远程数据包转发到本机 wireshark支持lua扩展解释自定义协议 "
},
{
"uri": "/other/aliyun/",
"title": "阿里云",
"tags": [],
"description": "",
"content": "开源mirror网址 阿里云专有网络 专有网络是您独有的云上虚拟网络,您可以将云资源部署在您自定义的专有网络中. 云资源不可以直接部署在专有网络中,必须属于专有网络内的一个交换机(子网)内. 目前专有网络必须手动开启ipv6功能 阿里云支持ipv6 阿里云ECS配置ipv6 VPC和ECS支持双栈后,ECS上会分配到IPv6地址,部署在ECS上的系统需要主动访问Internet的IPv6系统,这就需要配合IPv6网关使用\n开通IPv6网关后,通过配置IPv6网关规则,允许VPC内指定IPv6地址访问公网,则指定的IPv6 ECS就可以主动访问公网了\n如不配置IPv6网关规则,默认ECS分配的IPv6地址只能在VPC内部通信\n安全组,源:\u0026quot;::/0\u0026quot;表示允许ipv6,源:\u0026ldquo;0.0.0.0/0\u0026quot;表示允许ipv4,要支持双栈就要同端口开放两个规则\nip6无法访问解决办法\n阿里云邮箱 默认开通 服务器名称 服务器地址 服务器端口号(非加密) 服务器端口号(SSL加密) POP3 pop3.aliyun.com 110 995 SMTP smtp.aliyun.com 25 465 IMAP imap.aliyun.com 143 993 subject不能太随意了,否则会认为垃圾邮件,被系统退信的! 发件邮箱最好加入白名单\n杂项 阿里云:云市场,买各种api接口 阿里云:云效代码托管,可能快速导入其他的repos 钉钉开放平台 弹性云手机-远程虚拟手机,可以批量安装测试 批量安装设置服务器 设置一台机器为种子,进行各种配置和安装 把种子机器导出为镜像 购买其他实例,选择从指定镜像初始化 号码隐私保护服务-真实号码绑定虚拟号码,其他人可用虚拟号码转到真实号码 阿里云ECS高危漏洞问题处理 # 升级系统及软件就能解决多数 yum -y upgrade 服务器vi乱码 cd ~ vi .vimrc set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936 set termencoding=utf-8 set encoding=utf-8 set number filetype on syntax on "
},
{
"uri": "/golang/package/",
"title": "常用包",
"tags": [],
"description": "",
"content": " awesome-宝库值得多看\n各个领域优秀库-中文版\nlo-基于泛型加强基础功能库\nfunk-基于泛型加强基础功能库\nbtree-google开源\nexp-官方扩展库值得一看\nstl4go-golang版的stl\ngorse-推荐系统\ngoreleaser-简化打包生成各个平台的包\nconc-更好用的并发\nfsm-有限状态自动机\nunioffice-golang读写doc/excel/ppt\ncludewego-字节跳动开源框架\nfastpb-更快的protobuf\ngogo-更快加强版protobuf\ntemplate-更快的格式化输出\nwails-打包go后端+前端成一个exe\nsupervisord-golang版supervisor\ngo-echarts-图形库\ngo-num-golang版的numpy\ncolly-爬虫框架\nffmt-更友好fmt\ncombin-排序组合\nset-泛型集合操作\ncarbon-方便的日期时间库\nvugu-纯golang的前端\nair-有变化就编码\ngota-golang版的pands\nplot-golang版plotnine\nfyne-跨平台gui\ngo-git-纯go实现git集成\ngo-cmp-自定义比较库\ngolang-opencv绑定\n另一个-opencv绑定\npdf-处理pdf库\nassert库\ngse-golang结巴分词\nchardet-编码猜测\nedlib-最小编辑距离及相似度\nTheAlgorithms-常见算法实现\ndatastructures-数据结构实现\nkratos-微服务\ncallvis-可视化调用\ndeadlock-死锁检测\n类似json处理csv\ncobra-优秀的命令行\n更丰富的errors\nmemcache\nredis\nmongodb\nmysql\ngrpc\ngrpc转换http接口\niris\ngin\necho\ngorm\nxorm\n发邮件\n更快的json\n漂亮json输出\n从json文档中直接读取相关值\ngohook动态替换函数\ngo-cache-内存缓存\n二维码\ntraceroute-路由跟踪\ntesseract-golang调用ocr\n在标准输出中彩色输出\ncombination-组合库\nperm-排列库\n中文GBK-utf8转换\n各种跨类型-复制\nbloom-布隆过滤器\n操作excel\n多种格式配置文件\n日志库-logrus\n日志库-glog\nwechat-微信SDK\ngopacket\n更方便httpclient\nswag文档\ngo-admin\ntidb数据库\nnsq实时消息\nOpenIM\nrpcx-微服务框架\ngo-zero\n360的goreporter,几年没更新估计死掉了\nChromedp\nchromedp是一个更快、更简单的Golang库用于调用支持Chrome DevTools协议的浏览器,同时不需要额外的依赖(例如Selenium和PhantomJS) Chrome DevTools其实就是Chrome浏览器按下F12之后的控制终端 golang-request\ngolang-另一个request\nxlsx-另一个xlsx库,已知bug,列名不能互相包含,否则出错\n检查代码中是否包括密码密钥之类gitleaks git clone https://github.com/zricethezav/gitleaks.git cd gitleaks make build # 主要可用在阻挡提交 # detect protect gitleaks detect -s=. -r=out.json 检查代码中sql安全gokart 检查代码安全gosec 检查魔术常量检查go-mnd "
},
{
"uri": "/nginx/use/",
"title": "常用技巧",
"tags": [],
"description": "",
"content": "配置片段 http转向https\nrewrite ^(.*) https://$server_name$1 permanent; rewrite ^(.*) https://$host$1 permanent; 两种写法,各有适合场合 $server_name, 由nginx配置决定 $host,由请求路径决定 正向代理\nserver { listen 80; location / { proxy_pass http://$host$request_uri; } } 配合日志,可以用来调试 可以过滤掉特定请求 可以检查http请求是否被拦截 解决无法加载样式表\n# 否则无法加载样式表 include /etc/nginx/mime.types; default_type application/octet-stream; 支持http2\n自定义安装带上v2,ssl\n./configure --prefix=/Users/Shared/nginx \\ --with-http_v2_module \\ --with-http_ssl_module \\ --with-openssl=/opt/homebrew/Cellar/[email protected]/1.1.1m\\ --with-debug 配置增加上http2\n... server { # 默认情况http2都走ssl,所以在ssl加上http2 listen 443 ssl http2; ... } ... 支持http3\n自定义安装带上v3,ssl,brotli\n./auto/configure --with-http_v3_module \\ --with-stream_quic_module \\ --with-http_ssl_module \\ --with-http_v2_module \\ --add-module=../ngx_brotli \\ --with-cc-opt=\u0026#34;-I../libressl/build/include\u0026#34; \\ --with-ld-opt=\u0026#34;-L../libressl/build/lib\u0026#34; 配置增加上http3\n... http { brotli on; brotli_comp_level 6; brotli_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml; server { # 默认情况http2都走ssl,所以在ssl加上http2 listen 443 ssl http2; listen 443 http3 reuseport; # UDP listener for QUIC+HTTP/3,在主域名表示reuseport,否则会提示冲突 ssl_protocols TLSv1.3; # QUIC requires TLS 1.3 # 一定要添加头部,否则无法开启 add_header alt-svc \u0026#39;h3=\u0026#34;:443\u0026#34;; ma=86400;quic=\u0026#34;:443\u0026#34;; ma=2592000; v=\u0026#34;46,43\u0026#34;, h3-Q050=\u0026#34;:443\u0026#34;; ma=2592000, h3-Q049=\u0026#34;:443\u0026#34;; ma=2592000, h3-Q048=\u0026#34;:443\u0026#34;; ma=2592000,h3-Q046=\u0026#34;:443\u0026#34;; ma=2592000, h3-Q043=\u0026#34;:443\u0026#34;; ma=2592000, h3-23=\u0026#34;:443\u0026#34;; ma=2592000\u0026#39;; ... } ... } ... 四层代理-stream\n自定义安装带上stream\n./configure --prefix=/Users/Shared/nginx \\ --with-stream \\ --with-debug make \u0026amp;\u0026amp; make install 配置增加上stream\n... stream { server { listen 8411; proxy_timeout 3s; proxy_pass xxx:8411; } } ... gzip-压缩支持\n... http { # 打开gzip指令,否则后面不会生效 gzip on; # 回包头部增加content-encoding: gzip gzip_vary on; # 压缩类型 gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml; } ... 映像/复制mirror\nlocation / { #可以多次映像/复制,从而起到放大流量功能 #产生一个http subrequest \u0026#34;/mirror?\u0026#34;,跳转到相应location #所以mirror结果(包括超时,服务器关闭,50x,40x等等),不影响这个本身速度及结果 #但是占用内存,消费conn连接池之类还是要的 #mirror /mirror; #mirror /mirror; mirror /mirror; #允许丢掉body #mirror_request_body off; proxy_pass http://backend; } location = /mirror { # 判断请求方法,不是GET返回403,用其他类似手段缩小流量规模 # if ($request_method != GET) { # return 403; # } internal; #这里的回包是忽略 proxy_pass http://test_backend$request_uri; #允许丢掉body #proxy_pass_request_body off; #proxy_set_header Content-Length \u0026#34;\u0026#34;; proxy_set_header X-Original-URI $request_uri; } 利用日志调试\nserver { ... #降低错误日志等级,例如notice,如果编译带有--with-debug,则可以debug,debug_http error_log logs/error.log info; #不同路径不同access日志文件,确认哪个loc使用 location /hello { ... access_log logs/hello_access.log; ... } location /world { ... access_log logs/world_access.log; ... } ... } root与alias区别\n# 请求/abc/123 ==\u0026gt; /var/www/app/static/abc/123 location /abc { # In case of the root directive, full path is appended to the root including the location part # 请求的path附加上root指定path,组合本地路径 root /var/www/app/static; autoindex off; } # 请求/abc/123 ==\u0026gt; /var/www/app/static/123 location /abc { # only the portion of the path NOT including the location part is appended to the alias. # 请求的path移除掉location的path,再附加上alias指定path,组合本地路径 alias /var/www/app/static; autoindex off; } 常用模块 http_memcached模块\n... location /memcached { set $memcached_key \u0026#34;$uri\u0026#34;; memcached_pass 127.0.0.1:11211; #指示返回为html,方便浏览器直接显示 default_type text/html; error_page 404 502 504 = @notexit; } location @notexit { #echo为第三方模块引入指令,方便调试 echo \u0026#34;noexit$uri\u0026#34;; } ... sequenceDiagram actor u as user actor n as nginx actor m as memcached u-\u003e\u003en: http请求/memcached n-\u003e\u003em: get命令key值为$uri(/memcached) m-\u003e\u003en: 存在则返回值,否则返回空 n-\u003e\u003eu: 成功获取,则直接返回,否则转跳notexit ngx_http_redis第三方模块,类似http_memcached\n./configure --prefix=/Users/Shared/nginx \\ --add-module=../nginx-party-module/ngx_http_redis-module \\ ... --with-debug make \u0026amp;\u0026amp; make install ... location /redis { set $redis_key \u0026#34;$uri\u0026#34;; redis_pass 127.0.0.1:6379; #指示返回为html,方便浏览器直接显示 default_type text/html; error_page 404 502 504 = @notexit; } location @notexit { #echo为第三方模块引入指令,方便调试 echo \u0026#34;noexit$uri\u0026#34;; } ... sequenceDiagram actor u as user actor n as nginx actor m as redis u-\u003e\u003en: http请求/redis n-\u003e\u003em: get命令key值为$uri(/redis) m-\u003e\u003en: 存在则返回值,否则返回空 n-\u003e\u003eu: 成功获取,则直接返回,否则转跳notexit redis2-nginx-module第三方模块,更强大更多操作\n./configure --prefix=/Users/Shared/nginx \\ --add-module=../nginx-party-module/redis2-nginx-module \\ --with-debug make make install ... location = /foo { set $value \u0026#39;\u0026lt;html\u0026gt;\u0026lt;H1\u0026gt;From Nginx Redis\u0026lt;/H1\u0026gt;\u0026lt;/html\u0026gt;\u0026#39;; redis2_query set one $value; redis2_pass 127.0.0.1:6379; } location = /get { redis2_query get one; redis2_pass 127.0.0.1:6379; } ... sequenceDiagram actor u as user actor n as nginx actor r as redis u-\u003e\u003en: http请求/get n-\u003e\u003er: get命令key值为one r-\u003e\u003en: 标准命令处理 n-\u003e\u003eu: 返回原始键值 常见问题 server_names_hash问题\n[emerg] could not build server_names_hash, you should increase server_names_hash_bucket_size: 32 解决办法\n# 如果不够,继续增加,大小必须是32*n server_names_hash_bucket_size 64; invalid request问题\n# asscess.log 有这种提示 \u0026#34;PRI * HTTP/2.0\u0026#34; 400 157 \u0026#34;-\u0026#34; \u0026#34;-\u0026#34; # error.log 有这种提示 client sent invalid request while reading client request line 解决办法-客户端没有采用ssl,tls,但访问nginx配置需要ssl\nphp-fpm出现Primary script unknown问题\n尝试修改nginx配置\n# FastCGI sent in stderr: \u0026#34;Primary script unknown\u0026#34; while reading response header from upstream, # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 如果仍然不行,则打开php-fpm.conf日志配置\naccess.log = /var/log/php-fpm.$pool.access.log 再打开nginx日志配置\n# http log_format scripts \u0026#39;$document_root$fastcgi_script_name \u0026gt; $request\u0026#39;; # server access_log /usr/local/nginx/scripts.log scripts; 重启nginx,和php-fpm 查看日志,一般是路径不对和权限不对\nphp-fpm出现无法连接数库,可能是编译参数不对\n./configure --enable-fpm --prefix=/usr/local/php --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd 不知道当前nginx所用配置文件\n# 获取nginx进程号 ps -ef | grep nginx # 获取nginx路径 cd /proc/pid ls -a # 执行相应路径的语法测试,输出就能看到路径 nginx -t 不知道当前nginx的编译参数\n# 获取nginx进程号 ps -ef | grep nginx # 获取nginx路径 cd /proc/pid ls -a # 执行相应路径的语法测试,输出就能看到路径 nginx -V "
},
{
"uri": "/golang/code/",
"title": "代码片断",
"tags": [],
"description": "",
"content": "更丰富的errors import ( \u0026#34;fmt\u0026#34; \u0026#34;github.com/pkg/errors\u0026#34; ) func main() { //%+v格式输出,则带上栈调用,调试好帮手 fmt.Printf(\u0026#34;err:%+v\u0026#34;, errors.New(\u0026#34;mynew\u0026#34;)) } memcached package main import ( \u0026#34;fmt\u0026#34; //连接memcached \u0026#34;github.com/bradfitz/gomemcache/memcache\u0026#34; ) func main() { key := \u0026#34;/golang\u0026#34; client := memcache.New(\u0026#34;127.0.0.1:11211\u0026#34;) err := client.Set(\u0026amp;memcache.Item{ Key: key, Flags: 0, Expiration: 0, Value: []byte(\u0026#34;\u0026lt;HTML\u0026gt;\u0026lt;H2\u0026gt;hello,golang\u0026lt;/H2\u0026gt;\u0026lt;/HTML\u0026gt;\u0026#34;), }) if err != nil { fmt.Println(err.Error()) return } item, err2 := client.Get(key) if err2 != nil { fmt.Println(err2.Error()) return } fmt.Println(string(item.Value)) } redis package main import ( \u0026#34;fmt\u0026#34; //连接redis \u0026#34;github.com/gomodule/redigo/redis\u0026#34; ) func main() { conn, err := redis.Dial(\u0026#34;tcp\u0026#34;, \u0026#34;:6379\u0026#34;) if err != nil { fmt.Println(err.Error()) return } defer conn.Close() setReply, setReplyErr := redis.String(conn.Do(\u0026#34;set\u0026#34;, \u0026#34;firstKey\u0026#34;, \u0026#34;firstValue\u0026#34;)) if setReplyErr != nil { fmt.Println(setReplyErr.Error()) return } fmt.Println(\u0026#34;setReply:\u0026#34;, setReply, reflect.TypeOf(setReply)) mgetReplay, mgetReplyErr := redis.Strings(conn.Do(\u0026#34;mget\u0026#34;, \u0026#34;firstKey\u0026#34;, \u0026#34;k1\u0026#34;)) if mgetReplyErr != nil { fmt.Println(mgetReplyErr.Error()) return } fmt.Println(\u0026#34;mgetReplay:\u0026#34;, mgetReplay, reflect.TypeOf(mgetReplay)) hgetallReply, hgetallReplyErr := redis.StringMap(conn.Do(\u0026#34;hgetall\u0026#34;, \u0026#34;myhash\u0026#34;)) if hgetallReplyErr != nil { fmt.Println(hgetallReplyErr.Error()) return } fmt.Println(\u0026#34;hgetallReply:\u0026#34;, hgetallReply, reflect.ValueOf(hgetallReply)) lrangeReply, lrangeReplyErr := redis.Strings(conn.Do(\u0026#34;lrange\u0026#34;, \u0026#34;mylist\u0026#34;, \u0026#34;0\u0026#34;, \u0026#34;-1\u0026#34;)) if lrangeReplyErr != nil { fmt.Println(lrangeReplyErr.Error()) return } fmt.Println(\u0026#34;lrangeReply:\u0026#34;, lrangeReply, reflect.ValueOf(lrangeReply)) smembersReply, smembersReplyErr := redis.Strings(conn.Do(\u0026#34;smembers\u0026#34;, \u0026#34;myset\u0026#34;)) if smembersReplyErr != nil { fmt.Println(smembersReplyErr.Error()) return } fmt.Println(\u0026#34;smembersReply:\u0026#34;, smembersReply, reflect.TypeOf(smembersReply)) zrangeReply, zrangeReplyErr := redis.Int64Map(conn.Do(\u0026#34;zrange\u0026#34;, \u0026#34;mySortedSet\u0026#34;, \u0026#34;0\u0026#34;, \u0026#34;-1\u0026#34;, \u0026#34;withscores\u0026#34;)) if zrangeReplyErr != nil { fmt.Println(zrangeReplyErr.Error()) return } fmt.Println(\u0026#34;zrangeReply:\u0026#34;, zrangeReply, reflect.TypeOf(zrangeReply)) } mongodb package main import ( \u0026#34;context\u0026#34; \u0026#34;fmt\u0026#34; \u0026#34;reflect\u0026#34; \u0026#34;time\u0026#34; //连接mongodb \u0026#34;go.mongodb.org/mongo-driver/bson\u0026#34; \u0026#34;go.mongodb.org/mongo-driver/mongo\u0026#34; \u0026#34;go.mongodb.org/mongo-driver/mongo/options\u0026#34; ) func main() { ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) defer cancel() client, err := mongo.Connect(ctx, options.Client().ApplyURI(\u0026#34;mongodb://localhost:27017\u0026#34;)) if err != nil { fmt.Println(\u0026#34;connect:\u0026#34;, err.Error()) return } defer client.Disconnect(ctx) // database,collection不存在,会自动创建,不必事先创建 col := client.Database(\u0026#34;firstDB\u0026#34;).Collection(\u0026#34;firstCol\u0026#34;) reply, err := col.InsertOne(ctx, bson.D{{\u0026#34;name\u0026#34;, \u0026#34;pai\u0026#34;}, {\u0026#34;value\u0026#34;, 3.14159}}) if err != nil { fmt.Println(\u0026#34;list:\u0026#34;, err.Error()) return } fmt.Println(reflect.ValueOf(reply)) } package main import ( \u0026#34;context\u0026#34; \u0026#34;database/sql\u0026#34; \u0026#34;fmt\u0026#34; \u0026#34;log\u0026#34; _ \u0026#34;github.com/go-sql-driver/mysql\u0026#34; ) func main() { // user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4\u0026amp;parseTime=True\u0026amp;loc=Local db, err := sql.Open(\u0026#34;mysql\u0026#34;, \u0026#34;root:@(127.0.0.1:3306)/mytest?charset=utf8mb4\u0026amp;parseTime=True\u0026amp;loc=Local\u0026#34;) if err != nil { fmt.Println(err.Error()) return } defer db.Close() ctx, stop := context.WithCancel(context.Background()) defer stop() rows, err := db.QueryContext(ctx, \u0026#34;SELECT v FROM js\u0026#34;) if err != nil { log.Fatal(err) } defer rows.Close() names := make([]string, 0) for rows.Next() { var name string if err := rows.Scan(\u0026amp;name); err != nil { log.Fatal(err) } names = append(names, name) } // Check for errors from iterating over rows. if err := rows.Err(); err != nil { log.Fatal(err) } fmt.Println(names) } //获取当前git的hash值 gitOut, gitErr := exec.Command(\u0026#34;bash\u0026#34;, \u0026#34;-c\u0026#34;, \u0026#34;git rev-parse --short HEAD\u0026#34;).Output() if gitErr != nil { fmt.Println(gitErr) return } trace package main import ( \u0026#34;os\u0026#34; \u0026#34;runtime/trace\u0026#34; ) func main() { trace.Start(os.Stderr) defer trace.Stop() ch := make(chan string) go func() { ch \u0026lt;- \u0026#34;hello,world\u0026#34; }() \u0026lt;-ch } #注意2\u0026gt;trace.out重定向,产生数据文件 go run main.go 2\u0026gt;trace.out #pprof,trace有些需要graphviz brew install graphviz #采用trace工具分析显示数据, go tool trace trace.out strings.TrimLeft去掉连续的字符,strings.TrimPerfix只去掉一次 profile import ( \u0026#34;github.com/pkg/profile\u0026#34; _ \u0026#34;net/http/pprof\u0026#34; ) // go http.ListenAndServe(\u0026#34;0.0.0.0:8080\u0026#34;, nil) func main() { // p.Stop() must be called before the program exits to // ensure profiling information is written to disk. p := profile.Start(profile.MemProfile, profile.ProfilePath(\u0026#34;.\u0026#34;), profile.NoShutdownHook) ... // You can enable different kinds of memory profiling, either Heap or Allocs where Heap // profiling is the default with profile.MemProfile. p := profile.Start(profile.MemProfileAllocs, profile.ProfilePath(\u0026#34;.\u0026#34;), profile.NoShutdownHook) // 采用web接口提供 http://localhost:8080/debug/profile go http.ListenAndServe(\u0026#34;0.0.0.0:8080\u0026#34;, nil) } # 等上步生成的的cpu.profile go tool pprof cpu.profile # 常见命令 top,前几个费时 web 输出临时svg图片展示 "
},
{
"uri": "/other/geocode/",
"title": "地理编码",
"tags": [],
"description": "",
"content": "地理编码 地理编码是指将地址或地名等位置描述转换为经纬度坐标的过程.\n出于国家安全考虑,公布出来的坐标信息一般是经过加偏的.\n逆地理编码 逆地理编码可将经纬度坐标转换为详细,标准的地址信息.\n常用接口 高\u0008德地图开放平台\n百度地图开放平台\ngoogle中国\n阿里云-云市场\n"
},
{
"uri": "/golang/generic/",
"title": "泛型",
"tags": [],
"description": "",
"content": "// go 1.18+ package main import ( \u0026#34;fmt\u0026#34; ) type SubType interface { int | string | float32 } // func Sub[T int | string | float32](array []T, ele T) []T { func Sub[T SubType](array []T, ele T) []T { res := make([]T, 0, len(array)) for _, a := range array { if a == ele { continue } res = append(res, a) } return res } func main() { fmt.Println(Sub([]string{\u0026#34;a\u0026#34;, \u0026#34;b\u0026#34;, \u0026#34;c\u0026#34;, \u0026#34;b\u0026#34;}, \u0026#34;b\u0026#34;)) fmt.Println(Sub([]int{10, 20, 30, 10}, 10)) } "
},
{
"uri": "/golang/groupby/",
"title": "泛型切片分组",
"tags": [],
"description": "",
"content": "func GroupBy[T any, U comparable](collection []T, iteratee func(T) U) map[U][]T { result := map[U][]T{} for _, item := range collection { key := iteratee(item) result[key] = append(result[key], item) } return result } "
},
{
"uri": "/other/",
"title": "更多",
"tags": [],
"description": "",
"content": "STMP发邮件 sequenceDiagram actor c as 邮件客户端 actor s as smtp服 actor o as 目标邮件服 actor u as 邮件接收者 c-\u003e\u003es: 登陆发邮件 s--\u003e\u003ec: 错误或者垃级邮件就退回 s-\u003e\u003eo: 成功中转发邮件 o--\u003e\u003es: 错误或者垃级邮件就退回 o-\u003e\u003eu: 成功放入用户邮箱 NewSQL flowchart LR SQL(SQL例如MySQL) --\u003e NoSQL(NoSQL例如MongoDB) NoSQL --\u003e newSQL(NewSQL例如CockroachDB,TiDB) 简述\nnewSQL 就是在传统关系型数据库上集成了 noSQL 强大的可扩展性 newSQL 生于云时代,天生就是分布式架构 CockroachDB TiDB 好用的搜索 whoogle-search-自建google元搜索 searxng-另一个searx SEARX-开源元搜索 百度开发者-搜索 必应国际版-搜索 goobe-程序员专用搜索 mengso-搜索引擎,采用opensearch方式才能用 yandex-搜索引擎,过滤得不够 专搜代码-source 专搜代码-search 专搜代码-publicwww chromium安装darkreader github下载 chromium安装 写好博客/wiki有用参考 官方文档/教程 github优秀项目的readme 搜索 Stackoverflow 「关于某个 Wiki 话题」,前 10 ~ 20 个问题; 阅读 Google 搜索「关于某个 Wiki 话题」,前 10 ~ 100 篇文章; 社区优秀的免费和付费书籍(如果有的话); 优秀的出版书籍(如果有的话) 华为手机自定义安装VLC 电脑安装华为手机助手 用数据线连接电脑和手机,手机开启HDB 下载VLC安装包 复制到手机 手机-\u0026gt;实用工具-\u0026gt;文件管理-\u0026gt;浏览-\u0026gt;下载与接收-\u0026gt;下载管理器-\u0026gt;点击apk\n小度音箱播放本地音乐 进入小度APP之后,点击上方配置的小度智能音箱\n点击进入设备设置。\n点击进入蓝牙设置。\n打开音箱蓝牙的开关。\n再打开手机的蓝牙功能,找到音箱的蓝牙名称。\n成功连接音箱蓝牙后,打开手机音乐即可在小度音箱中播放\n优秀工具 githubs中文社区 alist-各种网盘分享非常优秀,值得试试 腾讯兔小巢快速建立用户反馈系统,值得试试 wkhtmltopdf-html转pdf把html转化为pdf brew install --cask wkhtmltopdf riptutorial国内免费分享的书籍示例 无google全家桶的chromium jenkins jenkins-pipeline语法 jenkins-BlueOcean插件 drone-轻量级的jenkins onedev-java版gogs gogs本地代码托管 gitea本地代码托管 mermaid 中科大镜像 阿里云镜像 清华大学镜像 类似hugo-文档建站工具 cloc代码统计工具 企业管理系统 Discord社交软件 Slack社交软件 odoo以前openERP 禅道 LayaAirH5小游戏引擎 apijson apifox 八爪鱼-自动爬虫 clickhouse-联机分析(OLAP)的列式数据库管理系统(DBMS),用来分析现有数据,发现数据规律,商业模式好帮手. Apache Doris是由百度贡献的开源MPP分析型数据库产品,亚秒级查询响应时间,支持实时数据分析;分布式架构简洁,易于运维,可以支持10PB以上的超大数据集;可以满足多种数据分析需求,例如固定历史报表,实时数据分析,交互式数据分析和探索式数据分析等。 ClickHouse是俄罗斯的搜索公司Yandex开源的MPP架构的分析引擎,号称比事务数据库快100-1000倍,团队有计算机体系结构的大牛,最大的特色是高性能的向量化执行引擎,而且功能丰富、可靠性高。\n小知识 国内dns地址 腾讯 DNS 119.29.29.29 182.254.116.116 阿里DNS 223.5.5.5 223.6.6.6 2400:3200::1 百度DNS 180.76.76.76 114.114.114.114 2400:da00::6666 下一代互联网国家工程中心 240c::6666 240c::6644 域名解析ipv6地址,是增加AAAA记录 #采用ipv6 ping -6 host #mac ping6 host utm-虚拟机 detian linux可以正常启动 Username: debian Password: debian centos-stream9 root 密码同mac的帐户密码\nutm一个虚拟机对应一个utm文件,当初次创建可能需要iso,等iso安装完成了,编辑虚拟机属性,删除掉dvd就不会再安装\nbrave-另一个chromium rockylinux-centos开源替代品 openEuler欧拉OS-linux发行版 android studio-开发ide flutter-跨六个平台-为每个平台生成对应的工程目录,从而达到支持多平台目录 菜鸟教程-入门必看 Consul-服务发现和配置 优质chrome插件-国内下载离线安装 fastlane-自动部署工具 BUG监控-开发者报警 tesseract-谷歌的ocr开源 paddle-百度的ocr开源 PPOCRLabel-百度开源标注系统 chineseocr_lite-ocr开源 EasyOCR-ocr开源,基于tesseract chineseocr-ocr开源 cvat-开源标注系统 VoTT-微软开源标注系统 labelme-开源标注系统 labelImg-开源标注系统 via-开源标注系统 copilot-AI写代码 开源公司介绍-oschina Fabric-python自动化运维 dperf-百度开源压测工具 traefik-开源的边缘路由器,类似于nginx tensorflow-谷歌的人工智能开源 极验-交互式验证码 720-VR全景制作 upx-免费程序打包压缩神器 蓝湖 蓝湖是一款产品文档和设计图的共享平台,帮助互联网团队更好地管理文档和设计图。蓝湖可以在线展示Axure,自动生成设计图标注,与团队共享设计图,展示页面之间的跳转关系\nOCSP-在线证书状态协议 目的:验证SSL证书的有效性,以确保它未被吊销。 腾讯开源 百度开源 百度AI 阿里开源 腾讯-开发者社区 百度-开发者社区 阿里云-开发者社区 IBM-开发者社区 gitlab-开源gitlab dodefever-蒲公英托管平台,github开源地址 gitee-百度投资托管平台 coding-腾讯投资托管平台 工蜂-腾讯托管平台 云效-阿里云托管平台 企业微信添加机器人,实现接受webhook 钉钉添加机器人,实现接受webhook,钉钉开放平台 Tapd-让协作更敏捷 介绍不需要碎片整理 文件系统基于区块分配的设计使得磁盘上出现碎片的概率很低,延迟分配和自动的整理策略解放了操作系统的使用者,在多数情况下不需要考虑磁盘的碎片化; 固态硬盘的随机读写性能远远好于机械硬盘,随机读写和顺序读写虽然也有性能差异,但是没有机械硬盘的差异巨大,而频繁的碎片整理也会影响固态硬盘的使用寿命; 存在ipv0,ipv1,ipv2,ipv3,ipv5协议 ipv6难取代ipv4,IPv6的回环地址是:0:0:0:0:0:0:0:0或::,ipv4使用32bit/4字节,每组一个字节,4组,ipv6采用128bit/16字节,每组2个字节,8组. IPv6 协议在设计时没有考虑与 IPv4 的兼容性问题 NAT 技术很大程度上缓解了 IPv4 地址短缺的问题 更细粒度的管控 IPv4 地址并回收闲置的资源 谁有能力强制推行大家支持?国家虽有文件要求,但设备厂商、运营商、互联网服务提供商、软件开发者、用户这整个链路中,所有的人都把IPv4当必选方案,IPv6当可选方案。所有的人都有非常一致的思维:既然IPv4 100%能访问,IPv6不确定因素那么多,那我就直接全部用IPv4多好多省事。 这里测试ipv6 tcp粘包因为是传输字节流,解决办法是协议自定义消息边界 消息长度固定 消息中有包括长度的字段 采用特定字符串作为消息边界 Google perftools 它的主要功能就是通过采样的方式,给程序中cpu的使用情况进行“画像”,通过它所输出的结果,我们可以对程序中各个函数(得到函数之间的调用关系)耗时情况一目了然。 在对程序做性能优化的时候,这个是很重要的,先把最耗时的若干个操作优化好,程序的整体性能提升应该十分明显. HMM(隐马尔科夫模型) webtorrent-直接看p2p 开源工作流 开源免费的-pilot eoapi-postman开源替代品 [almalinux-centos社区版](https://almalinux.org/zh-hans/) 转换pdf为jpg图片 # -density 300设置渲染PDF的dpi。 # -trim删除与角像素颜色相同的所有边缘像素。 # -quality 100将JPEG压缩质量设置为最高质量。 magick convert -density 300 -trim a.pdf -quality 100 a.jpg 英特尔的NUC迷你电脑 二手服务器主机(无尘机房下来的,质量较好)-费电,响声大 NUC-性能低 AppImage(Linux apps that run anywhere) AppImage 是一个压缩的镜像文件,它包含所有运行所需要的依赖和库文件.你可以直接执行AppImage 文件不需要安装。. 当你把AppImage 文件删除,整个软件也被删除了。. 你可以把它当成windows系统中的那些免安装的exe文件。 jsonl(JSON Lines) JSON Lines 是一种文本格式,适用于存储大量结构相似的嵌套数据、在协程之间传递信息等。 它有如下特点:\n每一行都是完整、合法的 JSON 值;采用 \\n 或 \\r\\n 作为行分隔符; 采用 UTF-8 编码; 使用 jsonl 作为文件扩展名;建议使用 gzip 或 bzip2 压缩并生成 .jsonl.gz 或 .jsonl.bz2 文件,以便节省空间。\ngitlab gitlab-\u0026gt;偏好设置-\u0026gt;中文 wps WPS加载网页表格 第一步:在网页上找到自己想要的表格,如果不能复制粘贴的话,那么就勾选其网址,然后复制 第二步:打开Excel表格,在菜单中的数据选项卡中找到“自网站”,然后点击进入。 第三步:在弹出的页面中,选择“基本”,然后在下方的空格中粘贴刚刚复制好的网址,点击确定。 第四步:稍等一会儿,就会弹出导航器,里面就有刚刚网页上的表格,选择你想要的表格,然后点击下方的加载。 第五步:最后表格就会很完美的加载在你的Excel中,而且格式都是网页上一样的,避免你再次挑战格式的麻烦 快速选中多行、多列 鼠标选中某个单元格,按住 shift 键,然后鼠标点击另外一个单元单元格 kcp/quic/enet协议的区别 quic 是一个完整固化的 http 应用层协议,目前已经更名 http/3,指定使用 udp(虽然本质上并不一定需要 udp)。其主要目的是为了整合TCP协议的可靠性和udp协议的速度和效率,其主要特性包括:避免前序包阻塞、减少数据包、向前纠错、会话重启和并行下载等,然而QUIC对标的是TCP+TLS+SPDY,相比其他方案更重,目前国内用于网络游戏较少\nkcp 只是一套基于无连接的数据报文之上的连接和拥塞控制协议,对底层【无连接的数据报文】没有具体的限制,可以基于 udp,也可以基于伪造的 tcp/icmp 等,也可以基于某些特殊环境的非 internet 网络(比如各种现场通信总线),KCP协议就是在保留UDP快的基础上,提供可靠的传输,应用层使用更加简单.\nenet: 有ARQ协议。收发不用自己实现,提供连接管理,心跳机制。支持人数固定。自己实现跨平台。支持可靠无序通道。没有拥塞控制。线程不安全\n理解socks5协议的工作过程和协议细节 全球ip地址查询 luminati中国 Luminati是全球最大的代理服务,全球拥有3500万IP的住宅代理网络和零编码代理管理接口。爬取任何网络数据, 从不被屏蔽,从不被掩盖。Luminati是道德代理网络。 无界面浏览器 playwright-微软出品(https://github.com/microsoft/playwright) puppeteer-谷歌出品 phantomjs-停止开发 openwrite-次编写markdown多个平台发布 检测vps的ip是否被封,有人检测到http代理或socks5,则会临时被封几分钟 中国站长工具,同时采用国内及国外ping,如果都不行,则肯定是vps问题,否则就极可能被封.\ntraceroute(linux/mac),tracert(windows) xxx 追踪一下\n查看路由表\nmac系统 netstat -r Routing tables linux系统 route -n windows系统 route print 各大厂商的ocr接口 华为没有免费的 阿里和腾讯都有免费额度 baidu的效果最好 window10/11自带ocr api接口 https://blogs.windows.com/windowsdeveloper/2016/02/08/optical-character-recognition-ocr-for-windows-10/\nhttps://cloud.tencent.com/document/product/866/35945\nhttps://help.aliyun.com/document_detail/330957.html\nhttps://ai.baidu.com/ai-doc/REFERENCE/Ck3dwjhhu#%E8%8E%B7%E5%8F%96-access-token\n开源代码库可以通过关键字在 GitHub 中查找;教程博客可以在 Medium 这样的平台上搜索;API 则可在官方文档翻阅 埋点 是数据采集领域(尤其是用户行为数据采集领域)的术语,指的是针对特定用户行为或事件进行捕获、处理和发送的相关技术及其实施过程。比如用户某个icon点击次数、观看某个视频的时长等等。埋点的技术实质,是先监听软件应用运行过程中的事件,当需要关注的事件发生时进行判断和捕获 便宜的海外服务器 腾讯云孟买-特惠 代码相似度检查NiCad ocr错别字都是形近字,根据语义能否提示错别字? 常见usb接口 阿里云智能插件,仅支持java Antlr - 强大的开源语法分析工具 HAR HAR(HTTP档案规范),是一个用来储存HTTP请求/响应信息的通用文件格式,基于JSON。这种格式的数据可以使HTTP监测工具以一种通用的格式导出所收集的数据,这些数据可以被其他支持HAR的HTTP分析工具(包括Firebug、httpwatch、Fiddler等)所使用,来分析网站的性能瓶颈。\n开源的聊天应用RocketChat-替代微信 toml文件格式 开源替换Google Analytics-umamiOwn your website analytics 开源替换Google Analytics 应该是当今互联网使用最广泛的网站流量分析服务 次世代图片格式 JPEG XL、AVIF、WebP 2 AVIF 有损压缩效果最好,无损压缩非常糟糕。编码速度很慢。 JPEG XL 无损压缩效果最好,有损压缩较 AVIF 有些许差距。编码速度快。 WebP 2 无损压缩效果优秀,有损压缩的上限达到了 AVIF 的水平,但下限很低,不稳定。编码速度很慢 这里是 Ant Design 的 Vue 实现,开发和服务于企业级后台产品(https://2x.antdv.com/docs/vue/introduce-cn) github-404项目 "
},
{
"uri": "/other/search/",
"title": "搜索技巧",
"tags": [],
"description": "",
"content": " 搜索技巧就是在搜索关键字时,配合一些通配符,帮助快速定位到想要的结果\n搜索技巧常常作为SEO(Search Engine Optimization)技术学习的一部分\nSEO : 是一种通过了解搜索引擎,以及提高目的网站在有关搜索引擎内排名的方式\nintitle标题 keyword intitle:标题关键字 intext内容 keyword intext:内容关键字 site站内(还可以查看网站的收录情况) keyword site:cnblogs.com duckduckgo site:zhihu.com inurl链接 keyword inurl:video 限定时间段 keyword 2022..2022 info 介绍 info:zhihu.com cache 搜索引擎关于某项关键字的缓存 cache:keyword 双引号/书括号,禁止拆分 \u0026#34;keyword\u0026#34;《keyword》 Filetype过滤文件类型 keyword:pdf 减号,排除关键词 # python -广告 -推广 keyword -keyword2 模糊匹配 keyword*keyword define 关键词定义 define:keyword link 搜索与某个网址有关联的其他网址 keyword link:xxx.com bing高级搜索帮助 "
},
{
"uri": "/other/tencent/",
"title": "腾讯",
"tags": [],
"description": "",
"content": "微信公众号 清除微信公众号\n找到 文件传输助手, 发送 debugtbs.qq.com, 打开链接,清楚TBS内核,success 头像300*300像素左右\n页面模板位置 信息 开放平台\n微信允许手机号转账,不必加好友(支付宝也支持)\n移动APP集成报告\n"
},
{
"uri": "/other/opensource/",
"title": "优秀开源软件",
"tags": [],
"description": "",
"content": "mrdoc-觅思文档 其功能类似于国内的语雀平台、看云平台和飞书文档,国外的 GitBook 平台。 rustdesk-远程桌面 网络状态模拟器 opencv "
},
{
"uri": "/nginx/install/",
"title": "源码安装剖析",
"tags": [],
"description": "",
"content": " flowchart LR A(下载) --\u003e B(配置) B --\u003e C(编译) C --\u003e D(安装) D --\u003e E(运行) E --\u003e F(进阶) F --\u003e G(后记) 1.下载 wget https://nginx.org/download/nginx-1.21.6.tar.gz tar -zxvf nginx-1.21.6.tar.gz cd nginx-1.21.6 源代码目录,如下图所示:\n2. 配置 # prefix参数指定默认路径(安装,配置文件,日志目录, 临时目录等等) # with-debug参数增加调试日志,正式运行强烈建议不要此参数 ./configure --prefix=/Users/Shared/nginx --with-debug # 更多参数及详细说明见 ./configure --help 生成makefile文件,如下图所示: 生成objs子目录,如下图所示 生成ngx_modules.c文件,如下图所示: 3. 编译 # 实际上执行上一步生成的objs/makefile make 生成启用模块目标文件,如下图所示: 4. 安装 # 实际上执行上一步生成的objs/makefile make install 安装执行代码,如下所示: install: build test -d \u0026#39;$(DESTDIR)/Users/Shared/nginx\u0026#39; || mkdir -p \u0026#39;$(DESTDIR)/Users/Shared/nginx\u0026#39; test -d \u0026#39;$(DESTDIR)/Users/Shared/nginx/sbin\u0026#39; \\ || mkdir -p \u0026#39;$(DESTDIR)/Users/Shared/nginx/sbin\u0026#39; test ! -f \u0026#39;$(DESTDIR)/Users/Shared/nginx/sbin/nginx\u0026#39; \\ || mv \u0026#39;$(DESTDIR)/Users/Shared/nginx/sbin/nginx\u0026#39; \\ \u0026#39;$(DESTDIR)/Users/Shared/nginx/sbin/nginx.old\u0026#39; cp objs/nginx \u0026#39;$(DESTDIR)/Users/Shared/nginx/sbin/nginx\u0026#39; test -d \u0026#39;$(DESTDIR)/Users/Shared/nginx/conf\u0026#39; \\ || mkdir -p \u0026#39;$(DESTDIR)/Users/Shared/nginx/conf\u0026#39; .... test -d \u0026#39;$(DESTDIR)/Users/Shared/nginx/logs\u0026#39; \\ || mkdir -p \u0026#39;$(DESTDIR)/Users/Shared/nginx/logs\u0026#39; 安装目录,如下图所示: 5.运行 # /Users/Shared/nginx为configure中prefix参数指定 cd /Users/Shared/nginx/sbin # -t 表示检查配置文件是否正确 ./nginx -t ./nginx 日志目录,如下图所示: 查看帮助,如下图所示: ./nginx -h 查看调试日志,如下图所示: http { ... server { listen 80; server_name localhost; # 编译时需要带上--with-debug # 如果仅看http过程,则指定等级为debug_http error_log logs/error.log debug; location / { root html; index index.html index.htm; } } ... } 6. 进阶 1. 安装第三方模块及禁/启用自带模块 # ../nginx-party-module/echo-nginx-module是echo-nginx-module模块源代码目录 ./configure \\ --prefix=/Users/Shared/nginx \\ --without-http_empty_gif_module \\ --with-stream \\ --add-module=../nginx-party-module/echo-nginx-module \u0026ndash;without参数禁用自带模块 \u0026ndash;with参数启用自带模块 \u0026ndash;add-module参数安装第三方模块 2. 编译安装 make \u0026amp;\u0026amp; make install make时在objs目录产生一个addon子目录,保存echo-nginx-module模块相关文件,如下图所示: 3. 编辑nginx.conf,运行 cd /Users/Shared/nginx/conf vim nginx.conf .... # echo-nginx-module模块详细见项目网址 location /hello { echo \u0026#34;hello, world!\u0026#34;; } ... cd ../sbin ./nginx 4. 测试 curl http://localhost/hello hello,world! 5. 原理分析 configure脚本先引用auto目录下的options脚本,如下图所示: options脚本设参数默认值,如下图所示: configure脚本再引用auto目录下的modules脚本,如下图所示: modules脚本如果参数为yes则引入编译,如下图所示: objs目录的ngx_modules.c文件就会增加引入的模块名,如下所示:\n... ngx_module_t *ngx_modules[] = { \u0026amp;ngx_core_module, \u0026amp;ngx_errlog_module, \u0026amp;ngx_conf_module, \u0026amp;ngx_regex_module, \u0026amp;ngx_events_module, \u0026amp;ngx_event_core_module, \u0026amp;ngx_kqueue_module, \u0026amp;ngx_http_module, ... \u0026amp;ngx_stream_upstream_zone_module, NULL }; ... ngx_modules.h的声明引用ngx_modules.c中ngx_modules,如下图所示: nginx.c的main函数调用nginx_module.c中ngx_preinit_modules函数,如下图所示: nginx_module.c中ngx_preinit_modules函数使用ngx_modules.c中ngx_modules,如下所示:\nngx_int_t ngx_preinit_modules(void) { ngx_uint_t i; /* ngx_modules变量为ngx_modules.c中定义 */ for (i = 0; ngx_modules[i]; i++) { ngx_modules[i]-\u0026gt;index = i; ngx_modules[i]-\u0026gt;name = ngx_module_names[i]; } ngx_modules_n = i; ngx_max_module = ngx_modules_n + NGX_MAX_DYNAMIC_MODULES; return NGX_OK; } 动态配置和静态编译执行在此完美结合起来 7. 后记 这里有很多优秀的nginx第三方模块,可供下载使用\necho-nginx-module模块网址\n安装ssl\n./configure --prefix=/Users/Shared/nginx \\ --add-module=../nginx-party-module/ngx_http_redis-module \\ --with-http_v2_module \\ --with-http_ssl_module \\ --with-openssl=/opt/homebrew/Cellar/[email protected]/1.1.1m\\ --with-debug http_v2_module不一定需要ssl,浏览器一般强制需要 http_ssl_module需要ssl目录,在linux一般指ssl-devel,需要include/lib目录 如果make仍然出错,移除掉路径中.openssl/,默认和系统中路径不同,多了一级.openssl/ "
},
{
"uri": "/",
"title": "主页",
"tags": [],
"description": "",
"content": "建立自已的代码托管平台 总览 flowchart LR A(域名解析) --\u003e B(配置Nginx) B --\u003e C(配置gogs) C --\u003e D(git提交) D --\u003e E(golang使用) sequenceDiagram actor u as 用户 actor h as hosts actor n as Nginx actor g as Gogs actor f as 文件系统 u-\u003e\u003eh: mydomain.site h--\u003e\u003eu: 127.0.0.1 n-\u003e\u003en: 监听127.0.0.1 u-\u003e\u003en: `https://mydomain.site/what/up....` n-\u003e\u003e+g: `http://xx.xx.xx.xx:3000/what/up...` g-\u003e\u003ef: 读写 g--\u003e\u003e-n: http回包 n--\u003e\u003eu: https回包 域名解析 修改hosts\nvim /etc/hosts #配置mydomain.site的dns为本机 #如果域名有备案,可以跳过此步,直接增加域名的A记录 127.0.0.1 mydomain.site 申请域名证书\n现在都不走http,都走https.个人项目,所以申请免费证书.生产环境还是要收费证书.免费申请证书途径:\nfreessl网站 letsencrypt网站 阿里云SSL证书服务 又拍云SSL 证书服务 七牛云免费SSL证书 百度云SSL证书服务 腾讯云SSL证书服务 华为云SSL证书管理SCM 配置Nginx 安装nginx\nbrew install nginx # 如果遇到不能启动,尝试启动sudo brew services start nginx brew services start nginx nginx源码安装,点这里 其他方式安装,看这里 修改配置文件\n... server { listen 443 ssl; server_name mydomain.site; #mydomain.site.pem/mydomain.site.key #就是申请域名证书后,网站提供的相关文件 ssl_certificate ssl/mydomain.site.pem; ssl_certificate_key ssl/mydomain.site.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { #直接转发gogs目录 proxy_pass http://xx.xx.xx.xx:3000; } } ... 配置gogs 安装gogs\nwget https://dl.gogs.io/$VERSION/gogs_$VERSION_$OS_$ARCH.tar.gz tar -zxvf gogs_$VERSION_$OS_$ARCH.tar.gz cd gogs_$VERSION_$OS_$ARCH 其他方式安装,看这里 修改配置\n[server] DOMAIN = mydomain.site HTTP_PORT = 3000 //旧版本是修改ROOT_URL EXTERNAL_URL = https://mydomain.site/ 运行\n#后台守护进程运行 nohup ./gogs web \u0026amp; 创建仓库(可以导入其他的repos,快速创建)\n#假设用户名为what,仓库名为up,仓库必须为公开,则仓库地址: https://mydomain.site/what/up.git git使用 #git下载 git clone https://mydomain.site/what/up.git #增加代码及其他 .... #提交代码 git push golang使用 设置私域名,不走代理\ngo env -w GOPRIVATE=mydomain.site 代码使用\npackage main import ( \u0026#34;fmt\u0026#34; \u0026#34;mydomain.site/what/up\u0026#34; ) func main() { fmt.Println(up.Add(10, 10)) fmt.Println(up.Power(10, 10)) } 特别重要 保护眼晴\ndarkreader暗黑模式 mac深色模式 各个领域优秀库-github\nLife is short.You need python!\nprint(\u0026#34;hello, world\u0026#34;) Dead is coming. Let is Go! import ( \u0026#34;fmt\u0026#34; ) func main() { fmt.Println(\u0026#34;hello, world\u0026#34;) } 扫-扫 技术博客 项目实战 公众号 "
}]