> 2021年06月17日信息消化 ### 每天学点Golang #### My Ultimate Makefile for Golang Projects 原文: https://betterprogramming.pub/my-ultimate-makefile-for-golang-projects-fcc8ca20c9bb #### TL;DR ![Available targets](https://raw.githubusercontent.com/Phalacrocorax/memo-image-host/master/PicGo/1*PNETwT5zf3d1RF4eE5PFiA.png) #### Build and Test the Code ##### make build ```makefile build: mkdir -p out/bin GO111MODULE=on $(GOCMD) build -mod vendor -o out/bin/$(BINARY_NAME) . ``` It is a basic `go build` task that uses `vendor`. We export the binary in the `out/bin` directory. ##### make vendor ```makefile vendor: $(GOCMD) mod vendor ``` In my projects, I use the [go module](https://golang.org/ref/mod#go-mod-vendor) as my dependency management system. This target just calls the system to download the dependencies and put them in the `/vendor` directory. ##### make test/make coverage ```makefile test: ifeq ($(EXPORT_RESULT), true) GO111MODULE=off go get -u github.com/jstemmer/go-junit-report $(eval OUTPUT_OPTIONS = | tee /dev/tty | go-junit-report -set-exit-code > junit-report.xml) endif $(GOTEST) -v -race ./... $(OUTPUT_OPTIONS) ``` We run the tests with the `-race` option to detect if we have some race condition. If an export is expected, the results are exported in `junit` format. ```makefile coverage: $(GOTEST) -cover -covermode=count -coverprofile=profile.cov ./... $(GOCMD) tool cover -func profile.cov ifeq ($(EXPORT_RESULT), true) GO111MODULE=off go get -u github.com/AlekSi/gocov-xml GO111MODULE=off go get -u github.com/axw/gocov/gocov gocov convert profile.cov | gocov-xml > coverage.xml endif ``` Coverage is done with `go test`, and we can export this in different formats (`.cov` or `.xml`)*.* ##### make watch ```makefile watch: $(eval PACKAGE_NAME=$(shell head -n 1 go.mod | cut -d ' ' -f2)) docker run -it --rm -w /go/src/$(PACKAGE_NAME) -v $(shell pwd):/go/src/$(PACKAGE_NAME) -p $(SERVICE_PORT):$(SERVICE_PORT) cosmtrek/air ``` This target is used to reload your app while you develop. It uses [cosmtrek/air](https://github.com/cosmtrek/air) to refresh the app as soon as you have a change in your code, which is perfect when you’re developing an API. #### Linters As you can see, there are also a bunch of linter targets. What they do is obvious: - `make lint-yaml`: Use [yamllint](https://yamllint.readthedocs.io/en/stable/) on your project’s YAML files (I am sure you have plenty of those). - `make lint-go`: Use [golintci-lint](https://golangci-lint.run/) on your project to lint your Go code. I recommend having a `.golangci.yml` with your configuration on it. - `make lint-dockerfile`: Lint your Dockerfile. If you want to launch all linters with one command, you can just run `make lint`. #### Docker ```makefile docker-build: docker build --rm --tag $(BINARY_NAME) . docker-release: docker tag $(BINARY_NAME) $(DOCKER_REGISTRY)$(BINARY_NAME):latest docker tag $(BINARY_NAME) $(DOCKER_REGISTRY)$(BINARY_NAME):$(VERSION) # Push the docker images docker push $(DOCKER_REGISTRY)$(BINARY_NAME):latest docker push $(DOCKER_REGISTRY)$(BINARY_NAME):$(VERSION) ``` `docker-build` will build and tag your Docker image locally, and `docker-release` will push this image to your registry. If you are using Docker Hub, just let the variable `DOCKER_REGISTRY` empty and it will work perfectly. #### Gist ```makefile GOCMD=go GOTEST=$(GOCMD) test GOVET=$(GOCMD) vet BINARY_NAME=example VERSION?=0.0.0 SERVICE_PORT?=3000 DOCKER_REGISTRY?= #if set it should finished by / EXPORT_RESULT?=false # for CI please set EXPORT_RESULT to true GREEN := $(shell tput -Txterm setaf 2) YELLOW := $(shell tput -Txterm setaf 3) WHITE := $(shell tput -Txterm setaf 7) CYAN := $(shell tput -Txterm setaf 6) RESET := $(shell tput -Txterm sgr0) .PHONY: all test build vendor all: help ## Build: build: ## Build your project and put the output binary in out/bin/ mkdir -p out/bin GO111MODULE=on $(GOCMD) build -mod vendor -o out/bin/$(BINARY_NAME) . clean: ## Remove build related file rm -fr ./bin rm -fr ./out rm -f ./junit-report.xml checkstyle-report.xml ./coverage.xml ./profile.cov yamllint-checkstyle.xml vendor: ## Copy of all packages needed to support builds and tests in the vendor directory $(GOCMD) mod vendor watch: ## Run the code with cosmtrek/air to have automatic reload on changes $(eval PACKAGE_NAME=$(shell head -n 1 go.mod | cut -d ' ' -f2)) docker run -it --rm -w /go/src/$(PACKAGE_NAME) -v $(shell pwd):/go/src/$(PACKAGE_NAME) -p $(SERVICE_PORT):$(SERVICE_PORT) cosmtrek/air ## Test: test: ## Run the tests of the project ifeq ($(EXPORT_RESULT), true) GO111MODULE=off go get -u github.com/jstemmer/go-junit-report $(eval OUTPUT_OPTIONS = | tee /dev/tty | go-junit-report -set-exit-code > junit-report.xml) endif $(GOTEST) -v -race ./... $(OUTPUT_OPTIONS) coverage: ## Run the tests of the project and export the coverage $(GOTEST) -cover -covermode=count -coverprofile=profile.cov ./... $(GOCMD) tool cover -func profile.cov ifeq ($(EXPORT_RESULT), true) GO111MODULE=off go get -u github.com/AlekSi/gocov-xml GO111MODULE=off go get -u github.com/axw/gocov/gocov gocov convert profile.cov | gocov-xml > coverage.xml endif ## Lint: lint: lint-go lint-dockerfile lint-yaml ## Run all available linters lint-dockerfile: ## Lint your Dockerfile # If dockerfile is present we lint it. ifeq ($(shell test -e ./Dockerfile && echo -n yes),yes) $(eval CONFIG_OPTION = $(shell [ -e $(shell pwd)/.hadolint.yaml ] && echo "-v $(shell pwd)/.hadolint.yaml:/root/.config/hadolint.yaml" || echo "" )) $(eval OUTPUT_OPTIONS = $(shell [ "${EXPORT_RESULT}" == "true" ] && echo "--format checkstyle" || echo "" )) $(eval OUTPUT_FILE = $(shell [ "${EXPORT_RESULT}" == "true" ] && echo "| tee /dev/tty > checkstyle-report.xml" || echo "" )) docker run --rm -i $(CONFIG_OPTION) hadolint/hadolint hadolint $(OUTPUT_OPTIONS) - < ./Dockerfile $(OUTPUT_FILE) endif lint-go: ## Use golintci-lint on your project $(eval OUTPUT_OPTIONS = $(shell [ "${EXPORT_RESULT}" == "true" ] && echo "--out-format checkstyle ./... | tee /dev/tty > checkstyle-report.xml" || echo "" )) docker run --rm -v $(shell pwd):/app -w /app golangci/golangci-lint:latest-alpine golangci-lint run --deadline=65s $(OUTPUT_OPTIONS) lint-yaml: ## Use yamllint on the yaml file of your projects ifeq ($(EXPORT_RESULT), true) GO111MODULE=off go get -u github.com/thomaspoignant/yamllint-checkstyle $(eval OUTPUT_OPTIONS = | tee /dev/tty | yamllint-checkstyle > yamllint-checkstyle.xml) endif docker run --rm -it -v $(shell pwd):/data cytopia/yamllint -f parsable $(shell git ls-files '*.yml' '*.yaml') $(OUTPUT_OPTIONS) ## Docker: docker-build: ## Use the dockerfile to build the container docker build --rm --tag $(BINARY_NAME) . docker-release: ## Release the container with tag latest and version docker tag $(BINARY_NAME) $(DOCKER_REGISTRY)$(BINARY_NAME):latest docker tag $(BINARY_NAME) $(DOCKER_REGISTRY)$(BINARY_NAME):$(VERSION) # Push the docker images docker push $(DOCKER_REGISTRY)$(BINARY_NAME):latest docker push $(DOCKER_REGISTRY)$(BINARY_NAME):$(VERSION) ## Help: help: ## Show this help. @echo '' @echo 'Usage:' @echo ' ${YELLOW}make${RESET} ${GREEN}${RESET}' @echo '' @echo 'Targets:' @awk 'BEGIN {FS = ":.*?## "} { \ if (/^[a-zA-Z_-]+:.*?##.*$$/) {printf " ${YELLOW}%-20s${GREEN}%s${RESET}\n", $$1, $$2} \ else if (/^## .*$$/) {printf " ${CYAN}%s${RESET}\n", substr($$1,4)} \ }' $(MAKEFILE_LIST) ``` ### 每天学点设计 #### Okapi Design System (by UXstudio) https://www.figma.com/community/file/976753712508408962 Design System Basics **Consistency** A design system makes sure you're using the same rules and same elements throughout the product you’re designing. It forces you to be consistent. **Effectivity** A well-established design system also saves time: instead of creating basic elements from scratch all the time you can concentrate on the more complex ones. This speeds up the design process. **Collaboration** When more than one designer is working on the product they inevitably have to decide on some rules and guidelines. **Documentation** A design system is a documentation of best practices tailored to a specific product. It is great for onboarding new designers to the team, or to close the gap between other departments working with design such as product and development. - Are you designing for multiple platforms? - Which platform? Web / Android / iOS? - What kind of elements will you probably need to build the product? (E.g. if it’s a webshop you’ll probably need a lot of cards and filters) - Will there be a dark mode later on? [Naming conventions - Design System template](https://docs.google.com/spreadsheets/d/1Ja71Nd-L6yHuh9lhFlnmm2VI_lclbRKN3njHE2H8RgY/edit#gid=0) - Color - Primary, Secondary, Neutral, Text, Destructive, Confirmative, Link - Typography - H1~H4, Body Regular/Bold, Button Label - Atoms - Avatars, Buttons(L/M/S), List elements, Radio buttons, Switches, Tooltips, Slider - Text field(Inactive, Hover, Open, Error, Disabled, Success) - Elements - Cards: Upload, Media - Tables - Overlays ##### Tips ![Tips](https://raw.githubusercontent.com/Phalacrocorax/memo-image-host/master/PicGo/Tips.png) ##### ???? Color Theory Types of colour schemes: ###### Analogous Analogous color schemes are made by picking three colors that are next to each other on the color wheel. They are perceived as calm and serene. 类比色方案是通过挑选色轮上彼此相邻的三种颜色来实现的。它们被认为是平静和安宁的。 ###### Complementary Complementary color schemes are made by picking two opposite colors con the color wheel. They appear vibrant near to each other. 互补色方案是通过在色轮上挑选两种相反的颜色来实现的。它们在彼此附近显得很有活力。 ###### Split complementary Split complementary schemes are like complementary but they uses two adiacent colors of the complement. They are more flexible than complementary ones. 分裂互补方案与互补方案类似,但它们使用互补方案的两个相邻的颜色。它们比补色方案更灵活。 ###### Triadic Triadic color schemes are created by picking three colors equally spaced on the color wheel. They appear quite contrasted and multicolored. 三元配色方案是通过在色轮上选取等距的三种颜色来创建的。它们看起来很有对比性和多色性。 ###### Tetradic Tetradic color schemes are made form two couples of complementary colors in a rectangular shape on the color wheel. They are very versatile, and work best with one dominant color. 四色配色方案是在色轮上的一个长方形中形成两对互补色。它们是非常通用的,最好是用一种主导颜色。 ###### Square Square color schemes are like tetradic arranged in a square instead of rectangle. Colors appear even more contrasting. 方形配色方案就像四边形排列在一个正方形而不是矩形中。颜色显得更有对比性。 #### Resources - [Website Style Guide Resources](http://styleguides.io/) - [7 Basic Rules for Button Design](https://uxplanet.org/7-basic-rules-for-button-design-63dcdf5676b4) - [Grid System Library](https://grid.kkuistore.com/) A free library of grid system for iOS, Android and Bootstrap. Easy way to start your project with this set. - [The Responsive Website Font Size Guidelines](https://learnui.design/blog/mobile-desktop-website-font-size-guidelines.html) #### The 6 Levels of UX Maturity https://www.nngroup.com/articles/ux-maturity-model/ **Summary:** Our UX-maturity model has 6 stages that cover processes, design, research, leadership support, and longevity of UX. Use our quiz to get an idea of your organization’s UX maturity. 我们的用户体验成熟度模型有6个阶段,涵盖流程、设计、研究、领导支持和用户体验的长期性。使用我们的测验来了解你的组织的用户体验成熟度。 1. **Absent:** UX is ignored or nonexistent. 不存在。用户体验被忽视或不存在。 2. **Limited:** UX work is rare, done haphazardly, and lacking importance. 有限。用户体验工作很少,做得很草率,缺乏重要性。 3. **Emergent:** The UX work is functional and promising but done inconsistently and inefficiently. 新出现的。用户体验工作是功能性的,有前途的,但做得不一致,效率不高。 4. **Structured:** The organization has semisystematic UX-related methodology that is widespread, but with varying degrees of effectiveness and efficiency. 结构化的。组织有半系统的用户体验相关的方法,很普遍,但有不同程度的效果和效率。 5. **Integrated:** UX work is comprehensive, effective, and pervasive. 综合的。用户体验工作是全面的、有效的、普遍的。 6. **User-driven:** Dedication to UX at all levels leads to deep insights and exceptional user-centered–design outcomes. 以用户为导向。在所有层面上致力于用户体验,导致深刻的洞察力和以用户为中心的特殊设计结果。 ![img](https://raw.githubusercontent.com/Phalacrocorax/memo-image-host/master/uPic/nng-ux-maturity-levels-37.png) #### 性能优化 让你的页面更丝滑 原文:https://juejin.cn/post/6940574353926914084 ##### 减少HTTP请求 合并脚本和样式表 合并css和js文件,合并文件大小之后,大文件gizp之后不能超过33kb(不是一股脑的打包成一个),文件数量要适量。 配置多个域名和CDN加速 通常浏览器对于一个域名的并发请求是有限的,比如:有100个文件要加载,但浏览器一次只可能并发请求10个文件,这样并发多次就会耗时。因此配置多个域名能够最大限度的增加并发请求量。 但这里有个缺点就是会增加浏览器域名解析的次数,这里建议利用CDN来加载不是经常更新和修改的静态资源(图片,css库,js第三方库等等)。一个是CDN域名一般都会缓存到本地中,另一个是CDN网络请求速度是非常快的。 ##### 缓存策略 缓存的优先级:cache-control > expires > Etag > last-modified 在第一次请求时,浏览器会检查是否有缓存设置,记入内存,下次请求,服务器判断返回304从缓存取,200会从服务器取。 ###### cache-control 设置过期时间长度(秒),在这个时间范围内,浏览器就会直接读取缓存,当expires和cache-control都存在时,cache-control的优先级更大。 ###### expires 在http头中设置一个过期时间,这个过期时间之前,浏览器请求不会发出,从缓存中读取文件,除非缓存被清空,或者强制刷新,缺陷在于服务器时间和客户端的时间可能不一致,所有http1.1引入了cache-control来改进。 ###### etag 服务器返回资源时,如果头部有etag,资源在下次请求时会把值自动加到请求头if-none-match中,服务器可以对比这个值,确定资源是否发生变化,如果没有变化返回304。 ###### last-modified 服务器返回资源时,如果头部有last-modified,资源请求时机会把值加入到if-modified-since中,服务器可以对比这个值,确定资源是否发生变化返回304。 #### 传输加载优化 在nginx中配置`gzip: on` ![image.png](https://raw.githubusercontent.com/Phalacrocorax/memo-image-host/master/uPic/703f580c5a794cf7974c67082f70c3e5~tplv-k3u1fbpfcp-watermark.image) ##### Keep-Alive > 在http请求头中加入Connection: keep-alive来告诉对方这个请求响应完成后不要关闭,下一次咱们还用这个请求继续交流. *在nginx 配置中有两个比较重要的配置* ```nginx keepalive_timeout 65 # 保持连接的时间,也叫超时时间,单位秒 keepalive_request 100 # 最大连接上限 ``` 浏览器请求//xx.cn/a.js-->解析域名—>HTTP连接—>服务器处理文件—>返回数据-->浏览器解析、渲染文件。Keep-Alive解决的`核心问题`就在此,`一定时间内,同一域名多次请求数据,只建立一次HTTP请求,其他请求可复用每一次建立的连接通道`,以达到提高请求效率的问题。一定时间是可以配置的, HTTP1.1还是存在效率问题 - 串行的文件传输 - 连接数过多 HTTP/2对同一域名下所有请求都是基于流,也就是说同一域名不管访问多少文件,也只建立一路连接。同样Apache的最大连接数为300,因为有了这个新特性,最大的并发就可以提升到300,比原来提升了60倍! #### 懒加载 在可视化的窗口中才去加载图片,大大提高首次的渲染速度! 原生支持加loading属性需要浏览器支持 第三方插件 lazyload (opens new window) react-lazyload(opens new window) ### ???????? GitHub中文排行榜 - Shell - [Kubernetes Handbook](https://jimmysong.io/kubernetes-handbook/)——Kubernetes 中文指南/云原生应用架构实践手册 - [engyuhetao/shell](engyuhetao/shell) | Linux命令行与shell脚本编程大全案例 - [al0ne](https://github.com/al0ne)/**[nginx_log_check](https://github.com/al0ne/nginx_log_check)** Nginx日志安全分析脚本 - [Lancger](https://github.com/Lancger)/**[opslinux](https://github.com/Lancger/opslinux)** Linux运维手册(基础+frp内网穿透+分布式锁+Redis+Kafka+安全+漏洞扫描+Docker+ELFK+LVM+监控+CI/CD+数据库+翻墙+LDAP+MQ+minio对象存储+命令录制审计+IP出口+gmail邮件安全校验+Jaeger 分布式追踪+苹果app安全审核+pps包转发率+网卡多队列均衡等) #### 如何选择开源项目? 原文:https://program-think.blogspot.com/2009/02/how-to-choose-opensource-project.html #### ★License(授权协议、许可证) ##### ◇对商业闭源软件“很敌对”的协议 先说说“很敌对”的协议:GPL(详细解释请看“[这里](https://en.wikipedia.org/wiki/GNU_General_Public_License)”)。GPL 和闭源软件是有严重冲突的。通俗地说,如果某个软件使用了基于 GPL 协议的【动态库或静态库】,则【整个软件】必须也用 GPL 协议发布(这就是大名鼎鼎的【GPL 传染性】)。也就是说——如果你开发的是【闭源】软件,一旦发现自己想用的某个开源库属于 GPL 协议,即使功能再强再好用,也只好忍痛割爱了。 在此郑重提醒大伙儿,【切莫】抱侥幸心理,偷偷使用。一旦被雪亮的群众眼睛所发现,不光害了自己的名节,公司的名节也不保。 ##### ◇对商业闭源软件“不太友好”的协议 因为 GPL 对于商业闭源软件太不友好了,估计当年很多开源库的作者怨声载道。GNU 组织为了缓和一下矛盾,搞出了一个折衷的 LGPL 协议(详细解释看“[这里](https://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License)”)。这个协议相对 GPL 来说,宽松了一些:商业闭源软件在【不公开】代码的前提下,可以在产品中使用 LGPL 的开源库。所以 LGPL 属于商业“不太友好”的协议。 ##### ◇对商业闭源软件“很友好”的协议 最后来说一下“非常友好”的协议,比较出名的有这几种:[BSD](https://en.wikipedia.org/wiki/BSD_license)、[MPL(Mozilla)](https://en.wikipedia.org/wiki/Mozilla_Public_License)、[Apache](https://en.wikipedia.org/wiki/Apache_License)、[MIT](https://en.wikipedia.org/wiki/MIT_License)。这些协议不但允许项目的使用者使用开源库,有些还允许对开源库进行修改并重新分发。因此用起来特别爽。上述这几个协议在细节上有些小差异,大伙儿可以去它们官网瞧一下。 另外,有些开源软件使用公共域授权(Public Domain,详细解释看“[这里](https://en.wikipedia.org/wiki/Public_domain)”)。简单说,就是不作任何限制,软件的使用者可以为所欲为 #### ★技术层面的因素 假如你开发的是跨平台的项目,那么你选择开源项目就得考虑它支持哪些平台(硬件平台、操作系统平台、数据库平台)。 假如你开发的软件是性能敏感的,那选型的时候就要测试一下几个候选项目的性能指标。 现在安全问题越来越严重。如果你比较在意安全性的话,还得顺便调查一下候选项目是否有安全问题(比如缓冲区溢出的 bug、比如跨站脚本注入等)。 #### ★普及程度(用户的人气) 看某个开源项目是否被知名的软件或者公司采用 对于若干个候选项目,显然要优先考虑普及度高的那个。因为某个项目普及度高,至少说明(但不绝对)它比较成熟、稳定、安全。而且用的人多了之后,相应的文档也会多一些,碰到问题也容易找到人咨询。 #### ★其它的风险 ##### ◇“单点故障”的风险 很多项目过于依赖【个人英雄主义——光靠着一两个大牛完成整个项目。一旦大牛出现意外,必然导致整个项目受到严重影响。典型的例子就是 ReiserFS 文件系统的创始人 Hans Reiser。这位老兄由于谋杀妻子的罪名成立,被判入狱15年(对 IT 八卦有兴趣的同学可以看“这里”)。导致 ReiserFS 项目受到严重影响。 ##### ◇商业风险 开源项目被商业公司收购后,由于种种原因(商业、管理、政治等)导致该开源项目受到不利影响。 ### 一点收获 - 发现了mailbrew这个digest工具。非常好用。 - 可以综合各个Gmail账户的日程表 - Twitter Top links - Covid-19 - EP 29. 架构设计与 12fallacy(上) - 关于招聘,平常善于记录与总结。 - [如何做技术设计](https://mp.weixin.qq.com/s/0DW7ZM0BUbYzJNG8tMh6RA) - 理解需求, 理解现状, 方案调研, 技术评审 - "We spend a lot of time talking about everything we have to do. You have to finish 10 things at work. You have to exercise today. You have to cook dinner for your family. **Now, change one word in each sentence. You don’t “have” to. You “get” to.** You get to finish 10 things at work. You get to exercise today. You get to cook dinner for your family. The right perspective transforms your burdens into opportunities."