Pages in {{ .Title | singularize }}
23 | 24 | {{ range .Data.Pages }} 25 | 26 |{{ .Title }}
27 | 28 | 29 |{{ printf "%s" .Summary | markdownify }} 30 | 31 |
{{ end }} 32 | 33 | 36 |
├── .all-contributorsrc ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── share_request.md │ └── share_template.md ├── dependabot.yml ├── weekly-digest.yml └── workflows │ ├── links.yml │ └── monthly.yml ├── .gitignore ├── .markdownlint.json ├── .netlify └── state.json ├── CONTRIBUTING.md ├── CONTRIBUTORS ├── HISTORY.md ├── JOINUS.md ├── LICENSE ├── Makefile ├── README.md ├── SHARE_REQUEST_PROPOSAL.md ├── actions ├── go.mod ├── issuesinfo.json └── monthly.go ├── archetypes └── default.md ├── config.toml ├── content ├── _index.md ├── algorithms │ ├── 2020-12-27.md │ ├── 2020-12-28.md │ ├── 2020-12-29.md │ ├── 2020-12-30.md │ ├── 2021-01-01.md │ ├── 2021-01-03.md │ ├── 2021-01-06.md │ ├── 2021-01-08.md │ ├── 2021-01-09.md │ ├── 2021-01-11.md │ └── 2021-01-12.md ├── articles │ ├── 2018-05-31-batch-del-redis-key.md │ ├── 2018-11-11-golang-file-lock.md │ ├── 2019-11-07-Raft--易于理解的一致性算法.md │ ├── 2020-02-08-source_go_flag.md │ ├── _index.md │ ├── goroutine_and_channel │ │ └── README.md │ ├── how_to_profile │ │ └── how_to_profile.md │ ├── how_to_test │ │ └── README.md │ ├── sonarqube-for-golang │ │ ├── 2018-07-22-sonarqube-for-golang.md │ │ ├── Dockerfile │ │ ├── index.md │ │ └── run.sh │ ├── sony-gobreaker │ │ └── README.md │ └── sync │ │ ├── README.md │ │ ├── sync_Map_source_code_analysis.md │ │ ├── sync_cond_source_code_analysis.md │ │ ├── sync_mutex_source_code_analysis.md │ │ ├── sync_once_source_code_analysis.md │ │ ├── sync_rwmutex_source_code_analysis.md │ │ └── sync_waitgroup_source_code_analysis.md ├── discuss │ ├── 2018-05-08-anlayze-underscore-in-go.md │ ├── 2018-05-09-wechat-discuss.md │ ├── 2018-05-10-which-vendor-tool.md │ ├── 2018-05-13-declaring-variables-on-if-else.md │ ├── 2018-05-16-the-way-to-go.md │ ├── 2018-05-18-bitset-and-import-cycle-not-allowed.md │ ├── 2018-05-21-using-goroutines-on-loop-iterator-variables.md │ ├── 2018-05-22-go-string-to-byte-slice.md │ ├── 2018-05-23-wechat-discuss.md │ ├── 2018-05-28-pprof-in-go.md │ ├── 2018-06-07-dial-timeout-in-go.md │ ├── 2018-07-02-c1000k-on-linux.md │ ├── 2018-07-04-package-names.md │ ├── 2018-07-09-make-new-in-go.md │ ├── 2018-07-11-using_64bit_atomic_in_32bit_system.md │ ├── 2018-07-14-version-gopath-go-command.md │ ├── 2018-07-31-println-Println-and_context.md │ ├── 2018-08-02-apns-push-notification.md │ ├── 2018-08-02-go-shell.md │ ├── 2018-08-09-log-color-in-go.md │ ├── 2018-08-14-wechat-discuss.md │ ├── 2018-08-15-wechat-discuss.md │ ├── 2018-08-23-wechat-discuss.md │ ├── 2018-08-24-wechat-discuss.md │ ├── 2018-08-30-understanding-go-interfaces.md │ ├── 2018-09-04-wechat-discuss.md │ ├── 2018-09-05-git-system.md │ ├── 2018-09-14-tips-in-vscode.md │ ├── 2018-09-18-benchmark-tools.md │ ├── 2018-09-19-wechat-discuss.md │ ├── 2018-09-28-return-value-in-waitgroup.md │ ├── 2018-10-18-encOp.md │ ├── 2018-11-08-address_operators.md │ ├── 2018-11-08-aws-ec2-ssh-login-problem.md │ ├── 2018-11-09-force-to-use-keyed-struct-literals.md │ ├── 2018-11-29-config-in-go.md │ ├── 2018-12-04-change-to-go.md │ ├── 2018-12-04-wechat-discuss.md │ ├── 2018-12-07-wechat-discuss.md │ ├── 2018-12-11-wechat-discuss.md │ ├── 2018-12-25-macOS-time-synchronization.md │ ├── 2019-01-10-anlayze-range.md │ ├── 2019-02-20-bigdecimal-show-string.md │ ├── 2019-03-07-wechat-discuss.md │ ├── 2019-03-08-wechat-discuss.md │ ├── 2019-03-26-gopsutil.md │ ├── 2019-04-10-remove-local-branch-in-merged-master.md │ ├── 2019-05-15-jaeger.md │ ├── 2019-05-21-chromedp.md │ ├── 2019-06-19-gorm-mysql-timestamp.md │ ├── 2019-07-16-assign-and-range.md │ ├── 2019-07-17-global-variable-init.md │ ├── 2019-10-13-go-module-looping-package.md │ ├── _index.md │ └── log_color_test.go ├── harvest │ ├── _index.md │ └── harvest.md ├── home.md ├── interview │ ├── _index.md │ ├── articles │ │ ├── interview_analysis_1.md │ │ ├── interview_analysis_2.md │ │ ├── interview_analysis_3.md │ │ └── interview_analysis_4.md │ ├── interview-algorithm.md │ ├── interview-architecture.md │ ├── interview-data-structure.md │ ├── interview-database.md │ ├── interview-design.md │ ├── interview-golang-language.md │ ├── interview-network.md │ ├── interview-os.md │ └── interview-pen.md ├── night │ ├── 1-2018-03-21-goutil.md │ ├── 1-2019-03-14-daily-reading.md │ ├── 10-2018-06-28-net-http-part4.md │ ├── 104-2020-09-13-hashicorp-raft.md │ ├── 105-2020-10-03-go-zero-discuss.md │ ├── 11-2018-07-26-golang-jenkins-sonarqube.md │ ├── 12-2018-08-02-goroutine-GPM.md │ ├── 13-2018-08-09-kubernetes-guide.md │ ├── 14-2018-08-17-sync-pool-reading.md │ ├── 15-2018-08-23-pool-workshop-in-go.md │ ├── 16-2018-09-06-gateway-reading.md │ ├── 17-2018-09-20-grpcp.md │ ├── 18-2018-09-27-CovenantSQL-DH-RPC.md │ ├── 19-2018-11-08-http-router-in-go.md │ ├── 2-2018-04-11-teleport.md │ ├── 20-2018-11-15-go-test.md │ ├── 21-2018-11-28-errors-in-go.md │ ├── 22-2018-12-06-go-ide-discuss.md │ ├── 23-2018-12-13-drone-guide.md │ ├── 24-2018-12-23-go-mod-part-1.md │ ├── 25-2018-12-27-tsdb.md │ ├── 26-2019-01-03-blog-with-github-netlify.md │ ├── 27-2019-01-10-go-mod-part-2.md │ ├── 28-2019-01-17-go-mod-part-3.md │ ├── 29-2019-01-23-opentracing-jaeger-in-go.md │ ├── 3-2018-04-18-strings-part1.md │ ├── 30-2019-02-16-go-mod-part-4.md │ ├── 31-2019-02-23-flag.md │ ├── 32-2019-03-02-etcd-raft.md │ ├── 33-2019-03-07-defer-in-go.md │ ├── 34-2019-03-16-plan9-guide.md │ ├── 35-2019-03-21-reading-context.md │ ├── 36-2019-03-28-reading-k8s-context.md │ ├── 37-2019-04-01-talk-from-serverless-in-apache-pulsar.md │ ├── 38-2019-04-13-k8s-scheduler-reading.md │ ├── 39-2019-04-18-init-function-in-go.md │ ├── 4-2018-04-25-strings-part2.md │ ├── 40-2019-04-27-atomic-value-in-go.md │ ├── 41-2019-05-12-golint-golangci-lint.md │ ├── 42-2019-05-16-go-failpoint-design.md │ ├── 43-2019-05-23-gomonkey-framework-design-and-practives.md │ ├── 44-2019-05-29-go-map-reading.md │ ├── 45-2019-05-30-goim-reading.md │ ├── 46-2019-06-05-tidb-overview-reading.md │ ├── 47-2019-06-12-tidb-exector-reading.md │ ├── 48-2019-06-19-tidb-compiler-reading.md │ ├── 49-2019-06-26-tidb-transaction-reading.md │ ├── 5-2018-05-10-strings-part3.md │ ├── 50-2019-06-27-goland-practice.md │ ├── 51-2019-07-18-sync-errgroup.md │ ├── 52-2019-07-25-httprouter-guide.md │ ├── 53-2019-08-01-build-in-delete-from-map-in-go.md │ ├── 54-2019-08-14-tidb-sql-tools.md │ ├── 55-2019-08-15-go-webassembly-guide.md │ ├── 56-2019-08-22-channel-select-in-go.md │ ├── 57-2019-08-29-sync-semaphore.md │ ├── 58-2019-09-05-whats-new-in-go1.13.md │ ├── 59-2019-09-12-real-world-go-concurrency-bugs-in-paper-reading.md │ ├── 6-2018-05-17-strings-part4.md │ ├── 60-2019-09-19-ipfs-guide.md │ ├── 61-2019-09-26-go-module-goproxy-cn.md │ ├── 62-2019-10-10-go-micro-part1.md │ ├── 63-2019-10-17-go-style-and-go-advices.md │ ├── 64-2019-10-24-go-runtime.md │ ├── 65-2019-10-31-go-net.md │ ├── 66-2019-11-07-paper-reading-csp.md │ ├── 67-2019-11-14-sql-pool-reading.md │ ├── 68-2019-11-21-dive-into-network.md │ ├── 69-2019-11-28-devops.md │ ├── 7-2018-05-24-net-http-part1.md │ ├── 70-2019-12-05-go-details.md │ ├── 71-2019-12-12-go-ini.md │ ├── 72-2019-12-19-go-micro-2.md │ ├── 73-2019-12-28-qrpc.md │ ├── 74-2020-01-02-time-in-go-1-14.md │ ├── 75-2020-02-06-the-state-of-go-in-2020.md │ ├── 76-2020-02-20-kubernetes-scheduler-design.md │ ├── 77-2020-03-05-reading-go-earnings.md │ ├── 78-2020-03-11-go-scheduler-reading.md │ ├── 79-2020-03-12-go-micro-tools.md │ ├── 8-2018-05-31-net-http-part2.md │ ├── 80-2020-03-18-go2-generics.md │ ├── 81-2020-03-19-gorm-guide.md │ ├── 82-2020-03-21-talkgo-night-story.md │ ├── 83-2020-03-26-gobench.md │ ├── 84-2020-04-02-go-aligned.md │ ├── 85-2020-04-16-douyu-confgo.md │ ├── 86-2020-04-23-go-unsafe-pointer.md │ ├── 87-2020-04-29-goland-tips.md │ ├── 9-2018-06-14-net-http-part3.md │ ├── _index.md │ └── other │ │ ├── 16-2018-09-06-faas-provider.md │ │ ├── 16-2018-09-06-faas.pdf │ │ ├── 16-2018-09-06-openfaas-guide.md │ │ ├── 16-2018-09-06-queue-worker.md │ │ ├── 16-2018-09-06-quick-start.md │ │ ├── 16-2018-09-06-watchdog.md │ │ ├── 2-2018-04-11_voice.md │ │ ├── 2018-08-17-sync-pool-reading.pdf │ │ ├── sync-pool-demo │ │ ├── cmd │ │ │ └── makeslice.go │ │ ├── demo │ │ │ └── main.go │ │ ├── demo2 │ │ │ └── main.go │ │ └── main.go │ │ └── zap-learn │ │ ├── go.mod │ │ ├── go.sum │ │ ├── logger │ │ ├── logger.go │ │ ├── logger_test.go │ │ └── zap │ │ │ └── zap.go │ │ └── main.go ├── other │ ├── CONTRIBUTING.md │ ├── _index.md │ ├── awesome-tools-mac.md │ ├── dev-tools-vimrc.md │ └── goland-help.md └── proposal │ ├── _index.md │ └── changes-to-go.md ├── examples ├── README.md └── gin_examples │ ├── .gitignore │ ├── .gitkeep │ ├── ENDPOINTS.md │ ├── Makefile │ ├── README.md │ ├── cmd │ └── server │ │ └── main.go │ ├── docker-compose-dev.yml │ ├── go.mod │ ├── go.sum │ ├── pkg │ ├── auth │ │ ├── auth.go │ │ ├── auth_test.go │ │ ├── sessionId.go │ │ └── sessionId_test.go │ ├── config │ │ ├── config.go │ │ └── config_test.go │ ├── http │ │ ├── middleware.go │ │ ├── middleware_test.go │ │ ├── routes.go │ │ ├── server.go │ │ ├── userHandler.go │ │ └── userHandler_test.go │ ├── mock │ │ ├── repository.go │ │ └── service.go │ ├── postgres │ │ ├── postgres.go │ │ └── userrepository.go │ └── service │ │ └── userservice │ │ ├── userservice.go │ │ └── userservice_test.go │ └── user.go ├── gen_contributors.sh ├── go.mod ├── go.sum ├── layouts ├── _default │ ├── index.json │ └── list.html └── shortcodes │ └── badges.html ├── macos-terminal-proxy-set.md ├── package.json ├── practice └── reading-go-43 │ ├── README.md │ └── main.go ├── static ├── icons │ ├── Read Me.txt │ ├── demo-files │ │ ├── demo.css │ │ └── demo.js │ ├── demo.html │ ├── fonts │ │ ├── icomoon.eot │ │ ├── icomoon.svg │ │ ├── icomoon.ttf │ │ └── icomoon.woff │ ├── selection.json │ └── style.css ├── images │ ├── 2018-05-19-wechat-discuss-bitset.jpeg │ ├── 2018-05-28-discuss01.jpeg │ ├── 2018-05-28-discuss02.jpeg │ ├── 2018-05-28-discuss03.jpeg │ ├── 2018-05-28-discuss04.jpeg │ ├── 2018-05-28-discuss05.jpeg │ ├── 2018-05-28-discuss06.jpeg │ ├── 2018-05-28-discuss07.jpeg │ ├── 2018-05-28-discuss08.jpeg │ ├── 2018-05-31-night-reading-go-01.jpeg │ ├── 2018-05-31-night-reading-go-02.jpeg │ ├── 2018-05-31-night-reading-go-03.jpeg │ ├── 2018-07-24-night-reading-go-wechat-16-23.png │ ├── 2018-08-14-discuss-01.png │ ├── 2018-08-15-discuss-01.png │ ├── 2018-08-23-for-select.png │ ├── 2018-08-23-kafka-producer-consumer.png │ ├── 2018-08-23-spinning.png │ ├── 2018-08-30-interface.png │ ├── 2018-08-30-interface2.png │ ├── 2018-09-04-body.jpeg │ ├── 2018-09-05-gitlab.png │ ├── 2018-12-04-gio.png │ ├── 2018-12-11-night-reading-go.jpg │ ├── 2018-12-25-macOS-time-synchronization-01.jpg │ ├── 2018-12-25-macOS-time-synchronization-02.png │ ├── 20180628-1.jpeg │ ├── 20180628-2.jpeg │ ├── 20180628-3.jpeg │ ├── 20180628-4.jpeg │ ├── 2019-07-17-code01.png │ ├── 2019-07-17-go-program-init-sequence.jpg │ ├── 2020-03-24-github-trending-go-daily-no2.jpg │ ├── 2020-03-24-github-trending-go-monthly-no8.jpg │ ├── 2020-03-24-github-trending-go-weekly-no4.jpg │ ├── 2020-03-24-night-reading-go-wechat-subscripter.png │ ├── 2021-12-09-talkgo-night-10000-star.png │ ├── 450px-SIMD.svg.png │ ├── TotalConn01.jpeg │ ├── allcontributors-night-reading-go-20191107.jpg │ ├── appendLog.jpg │ ├── articles │ │ └── sonarqube-for-golang │ │ │ ├── 01.png │ │ │ ├── 02.png │ │ │ ├── 03.png │ │ │ ├── 04.png │ │ │ ├── 05.png │ │ │ ├── 06.png │ │ │ ├── 07.png │ │ │ ├── 08.png │ │ │ ├── 09.png │ │ │ ├── 10.png │ │ │ ├── 11.png │ │ │ ├── 12.png │ │ │ ├── 13.png │ │ │ ├── 14.png │ │ │ ├── 15.png │ │ │ ├── 16.png │ │ │ ├── 17.png │ │ │ ├── 18.png │ │ │ ├── 19.png │ │ │ ├── 20.png │ │ │ ├── 21.png │ │ │ ├── 22.png │ │ │ ├── 23.png │ │ │ ├── 24.png │ │ │ ├── 25.png │ │ │ ├── 26.png │ │ │ ├── 27.png │ │ │ ├── 28.png │ │ │ ├── 29.png │ │ │ ├── 30.png │ │ │ ├── 31.png │ │ │ ├── 32.png │ │ │ ├── 33.png │ │ │ ├── 34.png │ │ │ ├── 35.png │ │ │ ├── 36.png │ │ │ ├── 37.png │ │ │ ├── 38.png │ │ │ ├── 39.png │ │ │ ├── 40.png │ │ │ ├── 41.png │ │ │ ├── 42.png │ │ │ ├── 43.png │ │ │ ├── 44.png │ │ │ ├── 45.png │ │ │ ├── 46.png │ │ │ ├── 47.png │ │ │ ├── 48.png │ │ │ ├── 49.png │ │ │ └── 50.png │ ├── batch-del-redis-key_four.png │ ├── batch-del-redis-key_one.png │ ├── batch-del-redis-key_three.png │ ├── batch-del-redis-key_two.png │ ├── beijing-youdian-university.png │ ├── bell-outline-badged.svg │ ├── bilibili-fans-8000-20200320.jpg │ ├── bilibili_1w_chengjiu.jpg │ ├── bilibili_1w_screenshot.png │ ├── bilibili_kaoshi.png │ ├── favicon.ico │ ├── github_trending_developer_0521.png │ ├── github_trending_go_0521.png │ ├── go_import_init.png │ ├── golang-goroutine-object.png │ ├── goruntime.png │ ├── how_to_profile_torch.svg │ ├── https_connect.jpg │ ├── ifelsetwitter.png │ ├── image-20181222170909680-5469749.png │ ├── image-20181222171507017.jpg │ ├── image-20181222173117732-5471077.png │ ├── image-20181222180733266-5473253.png │ ├── image-20190114114255919.png │ ├── image-20190114114416109.png │ ├── image-20190114143908128.png │ ├── image-20190114150048184.png │ ├── image-20190114150708086.png │ ├── image-20190114150807984.png │ ├── image-20190114152930330.png │ ├── image-20190114153033918.png │ ├── image-20190121160422563.png │ ├── image-20190121160506187.png │ ├── import_cycle_not_allowed.jpeg │ ├── jetbrains1.png │ ├── jetbrains2.png │ ├── load_balance.jpeg │ ├── log-compact.jpg │ ├── mem_torch.svg │ ├── memstats.jpeg │ ├── miaosha.jpg │ ├── night-reading-go-180ags-growingio_20191107.png │ ├── night-reading-go-github-20180727095100.png │ ├── night-reading-go-github-20180727095101.png │ ├── night-reading-go-github-20180730135001.png │ ├── night-reading-go-github-20180808085426.png │ ├── night-reading-go-github-20180808102026.png │ ├── night-reading-go-github-20180808170026.png │ ├── night-reading-go-github-20180808170326.png │ ├── night-reading-go-github-trending_20180518142500.png │ ├── night-reading-go-github-trending_20180724162600.png │ ├── night-reading-go-github-trending_20180724203600.png │ ├── night-reading-go-github-trending_20180725062700.png │ ├── night-reading-go-github-trending_20180725062800.png │ ├── night-reading-go-github-trending_20180726204300.png │ ├── night-reading-go-juejin_20180517115400.png │ ├── night-reading-go-juejin_20180518090800.png │ ├── night-reading-go-juejin_20180518142500.png │ ├── night-reading-go-juejin_20180522152100.png │ ├── night-reading-go-star_20180516110400.png │ ├── night-reading-go-star_20180516115000.png │ ├── night-reading-go-star_20180518142500.png │ ├── night-reading-go-today-trending_all_no9_20191107.png │ ├── night-reading-go-today-trending_go_no2_20191107.png │ ├── night-reading-go-today-trending_go_no3_20191205.png │ ├── night-reading-go-traffic_20191107.png │ ├── night-reading-go-weekly-trending_go_no10_20191107.png │ ├── reading-go-share.png │ ├── reading_go_bilibili.jpg │ ├── reading_go_youtube.jpg │ ├── reading_go_youtube_1001.jpg │ ├── return_before_after_change01.jpeg │ ├── return_before_after_change02.jpeg │ ├── slowlog.jpeg │ ├── sync-map1.png │ ├── sync-map2.png │ ├── sync-map3.png │ ├── sync-map4.png │ ├── sync-map5.png │ ├── sync-map6.png │ ├── sync-map7.png │ ├── sync-map8.png │ ├── talkgo-night-1000-commits.png │ ├── talkgo_zsxq.jpg │ ├── talkgo_zsxq_category.png │ ├── talkgo_zsxq_share.jpg │ ├── timeSleep.jpeg │ ├── totalConn.jpeg │ ├── trending_developers.jpg │ ├── trending_go.jpg │ ├── trending_repos.jpg │ ├── unexport01.png │ ├── unexport02.png │ ├── unexport03.png │ ├── unexport04.png │ ├── unexport05.png │ ├── web-app │ │ └── unit-test.png │ ├── wechat │ │ ├── PinClipart.com_shipping-container-clip-art_3317140.png │ │ └── gopher_2021_cosplay-soft-edge.png │ ├── wechat_group_6.jpg │ ├── wechat_logo │ │ └── talkgo.png │ ├── weibo_csdn_other_forward.png │ ├── weibo_github_daily.png │ ├── weibo_jiangtao_csdn.png │ └── 架构.jpg └── javascripts │ ├── application.js │ └── lunr.min.js ├── talkgo.go ├── talkgo_test.go └── themes └── hugo-material-docs ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── archetypes └── default.md ├── exampleSite ├── config.toml ├── content │ ├── adding-content │ │ └── index.md │ ├── getting-started │ │ └── index.md │ ├── index.md │ ├── license │ │ └── index.md │ └── roadmap │ │ └── index.md └── static │ └── .gitkeep ├── images ├── screenshot.png └── tn.png ├── layouts ├── 404.html ├── _default │ ├── __list.html │ └── single.html ├── index.html ├── partials │ ├── comment.html │ ├── drawer.html │ ├── drawer_list.html │ ├── footer.html │ ├── footer_js.html │ ├── head.html │ ├── header.html │ ├── nav.html │ └── nav_link.html └── shortcodes │ ├── note.html │ └── warning.html ├── static ├── fonts │ ├── icon.eot │ ├── icon.svg │ ├── icon.ttf │ └── icon.woff ├── images │ ├── colors.png │ ├── favicon.ico │ ├── reading.png │ └── screen.png ├── javascripts │ ├── application.js │ ├── growingio.js │ └── modernizr.js └── stylesheets │ ├── application.css │ ├── palettes.css │ └── temporary.css └── theme.toml /.gitattributes: -------------------------------------------------------------------------------- 1 | *.* linguist-language=go -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | patreon: maiyang 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/share_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: '提案:如何发起一次分享请求?' 3 | title: '【发起分享提案】' 4 | labels: 分享话题, Go 夜读 5 | assignees: yangwenmai, changkun 6 | about: 此模板主要用于如何发起分享提案的小伙伴。 7 | --- 8 | 9 | ## <话题名称> 10 | 11 | (此话题的简短描述。) 12 | 13 | ## 诉求 14 | 15 | (分享讲师,分享核心点等。) 16 | 17 | 22 | 23 | ## 参考资料 24 | 25 | (你可以罗列出你对此话题的一些研究,以及你所掌握的一些参考资料,以便大家更好的了解这个分享提案。) 26 | 27 | ---- 28 | 29 | ## 备注 30 | 31 | 任何你想要表达的话语。 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/share_template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: '第 100 期<你的话题名称>' 3 | title: '【分享计划】' 4 | labels: 分享话题, Go 夜读, 预习资料 5 | assignees: yangwenmai, changkun 6 | about: 此模板主要是针对提交分享计划的小伙伴,否则请忽略。 7 | --- 8 | 9 | ## 【Go 夜读】 <话题名称> 10 | 11 | (对本期分享话题做一个简短说明。) 12 | 13 | ## 大纲 14 | 15 | ## 分享者自我介绍 16 | 17 | 你的名字,来自哪家公司,担任什么职务,Go 所承载的数据量等各方面。 18 | 19 | ## 分享时间 20 | 21 | 20XX-YY-ZZ 21:00 UTC+8 22 | 23 | ## 分享地址 24 | 25 | https://zoom.us/j/6923842137 26 | 27 | ## Slides 28 | 29 | (尽量使用可在线预览的幻灯片) 30 | 31 | 推荐使用以下 2 个 Slides 的某一个作为模板: 32 | 33 | - https://docs.google.com/presentation/d/1yZO6a9MKABDPZmmP0zlgQ-jf7ctTzT4WZwMn_NGUO98/edit?usp=sharing 34 | - https://docs.google.com/presentation/d/1clppbBqjxzPrj-26d_zVeJK2fFiXCsNVXYhKPjEZ4Tc/edit?usp=sharing 35 | 36 | ## 参考资料 37 | 38 | (你可以列出本次分享所涉及的参考资料,以便大家更好的预习。) 39 | 40 | ---- 41 | 42 | ## 备注 43 | 44 | 针对此次分享的 QA 请分享者在分享之后,整理同步到此 issues 后面。 45 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /.github/weekly-digest.yml: -------------------------------------------------------------------------------- 1 | # Configuration for weekly-digest - https://github.com/apps/weekly-digest 2 | publishDay: "thursday" 3 | canPublishIssues: true 4 | canPublishPullRequests: true 5 | canPublishContributors: true 6 | canPublishStargazers: true 7 | canPublishCommits: true -------------------------------------------------------------------------------- /.github/workflows/links.yml: -------------------------------------------------------------------------------- 1 | name: Links 2 | 3 | on: 4 | repository_dispatch: 5 | workflow_dispatch: 6 | schedule: 7 | - cron: "0 0 1 * *" 8 | 9 | jobs: 10 | linkChecker: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4.2.2 14 | 15 | - name: Link Checker 16 | uses: lycheeverse/lychee-action@v2.4.0 17 | with: 18 | args: --verbose --no-progress **/*.md **/*.html 19 | env: 20 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 21 | 22 | - name: Create Issue From File 23 | uses: peter-evans/create-issue-from-file@v5 24 | with: 25 | title: Link Checker Report 26 | content-filepath: ./lychee/out.md 27 | labels: report, automated issue -------------------------------------------------------------------------------- /.github/workflows/monthly.yml: -------------------------------------------------------------------------------- 1 | name: auto_monthly_recommend 2 | 3 | on: 4 | schedule: 5 | - cron: "0 12 1 * *" 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4.2.2 12 | - name: build-go 13 | run: | 14 | go env -w GO111MODULE=on 15 | cd actions && go build -o monthly monthly.go 16 | - name: create-issue 17 | env: 18 | GITHUB_TOKEN: ${{ secrets.TOKEN }} 19 | run: cd actions &&./monthly -c ./issuesinfo.json 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | 13 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 14 | .glide/ 15 | .DS_Store 16 | 17 | .idea 18 | 19 | talkgo 20 | night-reading-go 21 | 22 | # Ignore hugo generated files 23 | public/ 24 | resources/ 25 | .vscode 26 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "default": true, 3 | "MD007": false, 4 | "no-hard-tabs": false, 5 | "line-length": false, 6 | "no-inline-html": { 7 | "allowed_elements": ["img", "br", "sub", "b"] 8 | } 9 | } -------------------------------------------------------------------------------- /.netlify/state.json: -------------------------------------------------------------------------------- 1 | { 2 | "siteId": "6ec64a83-fe6a-4891-8090-d75129fa87be" 3 | } -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | yangwenmai 2 | mougeCM 3 | yuhao5 4 | charnlsxy 5 | AceDarkknight 6 | gnuos 7 | KISSMonX 8 | dumliu01 9 | hlily2005 10 | henrylee2cn 11 | shaqsnake 12 | TBWISK 13 | toontong 14 | zhongxuan123 15 | zhouxinxin19920802 16 | macaria 17 | DennisMao 18 | orangle 19 | HarbinZhang 20 | SwanSpouse 21 | mickey0524 22 | zhuzhenfeng-finogeeks 23 | xujiajun 24 | NichoZhang 25 | NichoZhang 26 | qclaogui 27 | john-deng 28 | jeasonstudio 29 | xpzouying 30 | zsy619 31 | yangfan21 32 | hundredlee 33 | mlboy 34 | liangyuanpeng 35 | abcdsxg 36 | ziyi-yan 37 | lpflpf 38 | EDDYCJY 39 | feirie 40 | jukylin 41 | feifeiiiiiiiiiii 42 | cuishuang 43 | JasonRD 44 | itcuihao 45 | wangriyu 46 | Littlesqx 47 | mchangxin 48 | Hokkaitao 49 | LIYINGZHEN 50 | wty4427300 51 | davygeek 52 | changkun 53 | LinkinStars 54 | azd1997 55 | dayuoba 56 | scylhy 57 | sober-wang 58 | xhochipe 59 | -------------------------------------------------------------------------------- /JOINUS.md: -------------------------------------------------------------------------------- 1 | # 如何加入 Go 夜读 SIG 小组? 2 | 3 | >已不再纳新。 4 | 5 | 你可以联系 Go 夜读 SIG 小组成员,最好准备以下内容: 6 | 7 | 1. 完整的自我介绍,包括: 8 | - 个人信息 9 | - 工作内容 10 | - 个人爱好 11 | - 对开源社区有哪些贡献? 12 | - 演讲的能力或经验 13 | 2. 你能为 SIG 小伙伴带来什么? 14 | - 你有什么优势 15 | - 你可以提供什么有价值的输出? 16 | 3. 你希望从这里获得什么? 17 | 18 | ## 加入规则 19 | 20 | Go 夜读 SIG 小组成员全员通过才能加入。 21 | 22 | ## 退出机制 23 | 24 | 主要有两种: 25 | - 自己申请退出。 26 | - 连续 2 个月未参加小组活动,可考虑自行退出。 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 talkgo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | HUGO = hugo 2 | 3 | all: clean 4 | $(if $(shell PATH=$(PATH) which $(HUGO)),hugo -D --minify,$(error "No $(HUGO) in PATH")) 5 | 6 | clean: 7 | rm -rf public resources -------------------------------------------------------------------------------- /SHARE_REQUEST_PROPOSAL.md: -------------------------------------------------------------------------------- 1 | # 如何发起分享提案? 2 | 3 | ## 背景 4 | 5 | 你是否经常困扰于某些 Go 话题没有人分享或者很少人关注?自己很想深入研究,但是却是形单影只,经常半途而废呢? 6 | 7 | Go 夜读提供给大家一种渠道,希望可以将探究深入到 Go 的方方面面,只要你愿意跟我们一同推动,那么非常欢迎你来发起分享提案(只需要四步)。 8 | 9 | ## 你的收获 10 | 11 | 作为提案的发起人,可以参与到此提案的完整创作过程的,包括提案规范化,提案有效性,提案潜在讲师的招募,讲师分享内容的提前审校与沟通。 12 | 13 | ## 提案流程 14 | 15 | ### 第一步 16 | 17 | https://github.com/talkgo/night/issues/new?template=share_request.md 18 | 19 | 20 | 填写标题,例如:`提案:如何阅读 Go 源码?` 21 | 填写提案正文。(也就是你对此话题的简述和你的一些诉求) 22 | 23 | 记得给自己的提案添加 👍 哦。(以便于引导更多的小伙伴给你 👍)。 24 | 25 | ### 第二步 26 | 27 | Go 夜读 SIG 小组会审核该提案,标记标签:`提案`、`投票`、`招募`。 28 | 29 | 🏷 解释: 30 | 31 | 提案:表示该 issue 是一个提案。 32 | 投票:处于投票阶段。(需要在一个月内得到 80 个 👍,才有可能被接受)。 33 | 招募:处于话题可接受讲师自愿报名和邀约讲师的阶段。 34 | 35 | ### 第三步 36 | 37 | 当此提案达到 30 个 👍,Go 夜读 SIG 小组会将此提案发布到微信公众号上来推广,以引导更多的小伙伴关注,并 👍 提案。 38 | 39 | ### 第四步 40 | 41 | 讲师发起分享计划来完成此提案。 42 | -------------------------------------------------------------------------------- /actions/go.mod: -------------------------------------------------------------------------------- 1 | module night/actions 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/dyweb/gommon v0.0.13 7 | github.com/google/go-github/v29 v29.0.3 8 | golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 9 | ) 10 | -------------------------------------------------------------------------------- /actions/issuesinfo.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"TalkGo 读书会月度推荐书单", 3 | "body":"欢迎大家踊跃推荐好书:\r\n\u003e来这里的小伙伴,一定给你喜欢的推荐书点个赞:+1:,点赞越高的书将有机会被选为 TalkGo 读书会的共读书目。\r\n推荐好书填写要求:\r\n1. 每个 comment 只推荐一本书\r\n2. 必须填写完整书名、作者(作者\u0026译者)、ISBN\r\n3. 必须填写中肯的书评和推荐理由\r\n4. 可以摘录精华文字,也可以附上合法的书籍相关链接\r\n复制以下 markdown 即可填写。\r\n```\r\n## 书名\r\n## 作者\r\n## ISBN\r\n## 分类\r\n文学/历史/传记/科技/经管等\r\n## 推荐语\r\n\u003e推荐语必须是你自己的书评推荐语,不接受非原创推荐语。\r\n## 精华摘录\r\n- 1.\r\n- 2.\r\n## 其他相关资料\r\n豆瓣/微信阅读/京东/Amazon链接,其他读后感、总结等。\r\n```", 4 | "labels":["推荐书籍"], 5 | "assignee":["yangwenmai"] 6 | } -------------------------------------------------------------------------------- /archetypes/default.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "{{ replace .Name "-" " " | title }}" 3 | date: {{ .Date }} 4 | draft: true 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /content/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Go 夜读" 3 | date: 2018-11-15T12:32:37+08:00 4 | weight: 1 5 | --- 6 | -------------------------------------------------------------------------------- /content/algorithms/2020-12-27.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2020-12-27 TalkGo 算法之美微信群今日讨论问题 3 | date: 2020-12-27T22:31:00+08:00 4 | --- 5 | 来源:『TalkGo 算法之美』微信群 6 | 7 | 时间:2020-12-27 8 | 9 | --- 10 | 11 | ## 算法之美微信群当日讨论列表 12 | 13 | 1. Leetcode双周赛第四题:得到连续 K 个 1 的最少相邻交换次数 14 | 原题链接:https://leetcode-cn.com/problems/minimum-adjacent-swaps-for-k-consecutive-ones/ 15 | 2. Q30 用插线板制作章鱼脚状线路 16 | 原题链接:https://leetcode-cn.com/leetbook/read/interesting-algorithm-puzzles-for-programmers/9l2pjv/ 17 | 18 | ## TalkGo 算法之美专栏更新 19 | 20 | 1. [AK F.\*ing leetcode 流浪计划](https://talkgo.org/t/topic/1441) 21 | 2. [AK F.\*ing leetcode 流浪计划之并查集](https://talkgo.org/t/topic/1442) 22 | -------------------------------------------------------------------------------- /content/algorithms/2020-12-28.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2020-12-28 TalkGo 算法之美第三期第一周第一阶段 3 | date: 2020-12-28T08:31:00+08:00 4 | --- 5 | 来源:『TalkGo 算法之美』微信群 6 | 7 | 时间:2020-12-28 8 | 9 | --- 10 | 11 | 周一题目的链接:https://talkgo.org/t/topic/1443 12 | 13 | ## 主题:树的构造 14 | 15 | ### 先重温下二叉树是怎么构造出来的吧 16 | [108. 将有序数组转换为二叉搜索树](https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree/) 17 | 18 | ### 附加题: 19 | [95. 不同的二叉搜索树 II](https://leetcode-cn.com/problems/unique-binary-search-trees-ii/) 20 | - Tips: 递归 21 | 22 | -------------------------------------------------------------------------------- /content/algorithms/2020-12-29.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2020-12-29 TalkGo 算法之美第三期第一周第二阶段 3 | date: 2020-12-29T08:31:00+08:00 4 | --- 5 | 来源:『TalkGo 算法之美』微信群 6 | 7 | 时间:2020-12-29 8 | 9 | --- 10 | 11 | - 2020.12.29 12 | TalkGo算法之美群今日讨论问题 13 | 1. 将有序数组转换为二叉搜索树 14 | 题目链接:https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree/ 15 | 题解链接:https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree/solution/108-jiang-you-xu-shu-zu-zhuan-huan-wei-e-muuy/(来源:木头(算法之美群内成员)) 16 | 17 | 2. 不同的二叉搜索树 II 18 | 原题链接:https://leetcode-cn.com/problems/unique-binary-search-trees-ii/ 19 | 题解链接:https://leetcode-cn.com/problems/unique-binary-search-trees-ii/solution/95-bu-tong-de-er-cha-sou-suo-shu-ii-di-g-qu38/(来源:木头(算法之美群内成员)) 20 | 21 | 关于如何建设好算法之美群: 22 | 吴俊伟:我觉得可以分两类人,一种是为了找工作而刷题的,一种是单纯为了学习算法。对于前一种可以多找些高频面试题,后一种就按照现在来就好了。提高参与度的话就让大家可以把自己觉得好的题目或者做不出来的题目,又或者是面试遇到的题目发出来让大家看看,一起讨论。 23 | 吴俊伟:还有平台可以不用局限leetcode,洛谷,计蒜客,牛客网,poj都行的 24 | 小林:可以发布一些算法比赛消息 25 | 吴俊伟:不过我们也可以照顾到这些人多发些面试常考的"经典"题 26 | 27 | -------------------------------------------------------------------------------- /content/algorithms/2020-12-30.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2020-12-30 TalkGo 算法之美第三期第一周第二阶段 3 | date: 2020-12-30T08:31:00+08:00 4 | --- 5 | 来源:『TalkGo 算法之美』微信群 6 | 7 | 时间:2020-12-30 8 | 9 | --- 10 | 11 | - 2020.12.30 12 | TalkGo算法之美群今日讨论问题 13 | 1. 算法之美第三期周三题目 14 | 原题链接以及群友题解(题解见评论):https://talkgo.org/t/topic/1443 15 | 2. 比赛消息 16 | 由群成员吴俊伟提供 17 | 牛客2020跨年场 18 | 比赛时间:2020-12-31 21:00:00 - 2021-01-01 00:30:00 19 | 比赛地址:https://ac.nowcoder.com/acm/contest/9854 20 | 21 | -------------------------------------------------------------------------------- /content/algorithms/2021-01-01.md: -------------------------------------------------------------------------------- 1 | title: 2021-01-01 TalkGo 算法之美第三期第一周第三阶段 2 | date: 2021-01-01T08:31:00+08:00 3 | 4 | 来源:『TalkGo 算法之美』微信群 5 | 6 | 时间:2021-01-01 7 | 8 | --- 9 | 10 | - 2021.1.1 11 | TalkGo算法之美群今日讨论要素 12 | 13 | 1. 算法之美第三期第一周周五题目链接:https://talkgo.org/t/topic/1443 14 | 2. leetcode435. 无重叠区间 (由群友木头提供) 15 | 原题链接:https://leetcode-cn.com/problems/non-overlapping-intervals/ 16 | 3. 群友roseduan分享刷题记录 17 | 链接:https://github.com/roseduan/algo-learn 18 | 4. 本周线上讨论会预定于明天(2020.1.2)下午两点举行,欢迎各位来参与讨论。 19 | 20 | -------------------------------------------------------------------------------- /content/algorithms/2021-01-03.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2021-01-03 TalkGo 算法之美第三期第一周第三阶段 3 | date: 2021-01-03T08:31:00+08:00 4 | --- 5 | 来源:『TalkGo 算法之美』微信群 6 | 7 | 时间:2021-01-03 8 | 9 | --- 10 | 11 | - 2021.1.3 12 | TalkGo算法之美群今日讨论要素 13 | 1. leetcode周赛:https://leetcode-cn.com/contest/weekly-contest-222/ 14 | 15 | 2. leetcode每日一题: 86. 分隔链表 16 | 原题链接:https://leetcode-cn.com/problems/partition-list/ 17 | 18 | -------------------------------------------------------------------------------- /content/algorithms/2021-01-06.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2021-01-06 TalkGo 算法之美第三期第二周第三阶段 3 | date: 2021-01-06T08:31:00+08:00 4 | --- 5 | 来源:『TalkGo 算法之美』微信群 6 | 7 | 时间:2021-01-06 8 | 9 | --- 10 | 11 | - 2021.01.06 12 | - TalkGo算法之美第三期第二周开始啦。 13 | 以下是周三题目的链接:https://talkgo.org/t/topic/1502 14 | 主题:二叉搜索树 15 | 16 | -------------------------------------------------------------------------------- /content/algorithms/2021-01-08.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2021-01-08 TalkGo 算法之美第三期第二周第三阶段 3 | date: 2021-01-08T08:31:00+08:00 4 | --- 5 | 来源:『TalkGo 算法之美』微信群 6 | 7 | 时间:2021-01-08 8 | 9 | --- 10 | 11 | - 2021.01.08 12 | - TalkGo算法之美第三期第二周开始啦。 13 | 以下是周五题目的链接:https://talkgo.org/t/topic/1502 14 | 主题:巧用遍历 15 | 16 | -------------------------------------------------------------------------------- /content/algorithms/2021-01-09.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2021-01-09 TalkGo 算法之美第三期第三周第二阶段 3 | date: 2021-01-09T08:31:00+08:00 4 | --- 5 | 来源:『TalkGo 算法之美』微信群 6 | 7 | 时间:2021-01-9 8 | 9 | --- 10 | 11 | - 2021.10.9 12 | - TalkGo算法之美群今日讨论要素 13 | 1. leecode每日一题:123. 买卖股票的最佳时机 III 14 | 链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/ 15 | 16 | -------------------------------------------------------------------------------- /content/algorithms/2021-01-11.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2021-01-11 TalkGo 算法之美第三期第三周第一阶段 3 | date: 2021-01-11T08:31:00+08:00 4 | --- 5 | 来源:『TalkGo 算法之美』微信群 6 | 7 | 时间:2021-01-11 8 | 9 | --- 10 | 11 | - 2021.1.11 12 | - TalkGo算法之美第三期第三周开始啦。 13 | 以下是周一题目的链接:https://talkgo.org/t/topic/1550 14 | 主题:回溯 15 | 16 | -------------------------------------------------------------------------------- /content/algorithms/2021-01-12.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2021-01-12 TalkGo 算法之美第三期第三周第二阶段 3 | date: 2021-01-12T08:31:00+08:00 4 | --- 5 | 来源:『TalkGo 算法之美』微信群 6 | 7 | 时间:2021-01-12 8 | 9 | --- 10 | 11 | - 2021.1.12 12 | TalkGo算法之美群今日讨论要素 13 | 14 | 1. 百度面试题(群友bill提供):https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/ 15 | 16 | 2. 腾讯面试题(群友小林提供):https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/ 17 | 3. 每日一题题解:https://talkgo.org/t/topic/1561 18 | 4. 面试高频题(群友bill提供):https://leetcode-cn.top/#/home 19 | -------------------------------------------------------------------------------- /content/articles/2018-05-31-batch-del-redis-key.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 批量删除redis中的key 3 | date: 2018-05-31T00:00:00+08:00 4 | --- 5 | 6 | * **1.首先看图** 7 | 8 |  9 | 10 | 11 | >* 1.我创建了三个以`go:read`开头的key 12 | >* 2.通过`keys go:read:*`可以全部找出来 13 | >* 3.接下来退出redis-cli,使用`redis-cli -p 6379 keys "go:read*" | xargs redis-cli -p 6379 del`可以批量删除 14 | 15 | * **2.查看原理** 16 | 17 |  18 | 19 | >* 1.执行`redis-cli -p 6379 keys "go:read*"`控制台输出了需要的key 20 | >* 2.执行`redis-cli -p 6379 keys "go:read*" | xargs -0 echo`,可以看到输出了需要的key,但是有点不一样,双引号被去掉了,这说明数据通过管道传递给了xargs作了相应处理 21 | >* 3.执行`redis-cli -p 6379 keys "go:read*" | xargs redis-cli -p 6379 del`删除了输出的key,这说明xargs对接收到数据分别进行了`redis-cli -p 6379 del`操作 22 | 23 | * **3.遇到的问题** 24 | 25 |  26 | 27 | >* 1.同样的原理,我设置了三个key,但是这三个key里面包含了双引号,双引号前得加上\转义符 28 | >* 2.使用`redis-cli -p 6379 keys "go:read*" | xargs redis-cli -p 6379 del`,发现没删除 29 | >* 3.通过`redis-cli -p 6379 keys "go:read*" | xargs -0 echo`,发现传输到xargs时把\转义符删掉了,去执行redis del操作的时候key不配,导致删除失败 30 | >* TODO 采用xargs我没找到解决方案,希望各位大神求助,有方法了可以写在下面@~@ 31 | >* 32 | 33 | 34 | * **4.另一种解决方案** 35 | 36 |  37 | 38 | >* `for i in $(redis-cli -p 6379 keys "go:read:*");do redis-cli -p 6379 del "$i";done` 39 | >* 采用shell脚本格式 -> for循环读取key去删除 -------------------------------------------------------------------------------- /content/articles/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "分享文章" 3 | date: 2018-11-15T12:32:37+08:00 4 | weight: 5 5 | --- 6 | -------------------------------------------------------------------------------- /content/articles/sonarqube-for-golang/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8 2 | 3 | ENV SONAR_VERSION=7.2.1 \ 4 | SONARQUBE_HOME=/opt/sonarqube \ 5 | SONARQUBE_JDBC_USERNAME=sonar \ 6 | SONARQUBE_JDBC_PASSWORD=sonar \ 7 | SONARQUBE_JDBC_URL= 8 | 9 | 10 | # Http port 11 | EXPOSE 9000 12 | 13 | RUN groupadd -r sonarqube && useradd -r -g sonarqube sonarqube 14 | 15 | # grab gosu for easy step-down from root 16 | RUN set -x \ 17 | && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.10/gosu-$(dpkg --print-architecture)" \ 18 | && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/1.10/gosu-$(dpkg --print-architecture).asc" \ 19 | && export GNUPGHOME="$(mktemp -d)" \ 20 | && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \ 21 | && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \ 22 | && rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc \ 23 | && chmod +x /usr/local/bin/gosu \ 24 | && gosu nobody true 25 | 26 | RUN set -x \ 27 | && cd /opt \ 28 | && wget -O sonarqube.zip https://sonarsource.bintray.com/Distribution/sonarqube/sonarqube-$SONAR_VERSION.zip \ 29 | && unzip sonarqube.zip \ 30 | && mv sonarqube-$SONAR_VERSION sonarqube \ 31 | && chown -R sonarqube:sonarqube sonarqube \ 32 | && rm sonarqube.zip \ 33 | && rm -rf $SONARQUBE_HOME/bin/* 34 | 35 | VOLUME "$SONARQUBE_HOME/data" 36 | 37 | WORKDIR $SONARQUBE_HOME 38 | COPY run.sh $SONARQUBE_HOME/bin/ 39 | ENTRYPOINT ["./bin/run.sh"] -------------------------------------------------------------------------------- /content/articles/sonarqube-for-golang/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [ "${1:0:1}" != '-' ]; then 6 | exec "$@" 7 | fi 8 | 9 | chown -R sonarqube:sonarqube $SONARQUBE_HOME 10 | exec gosu sonarqube \ 11 | java -jar $SONARQUBE_HOME/lib/sonar-application-$SONAR_VERSION.jar \ 12 | -Dsonar.log.console=true \ 13 | -Dsonar.jdbc.username="$SONARQUBE_JDBC_USERNAME" \ 14 | -Dsonar.jdbc.password="$SONARQUBE_JDBC_PASSWORD" \ 15 | -Dsonar.jdbc.url="$SONARQUBE_JDBC_URL" \ 16 | -Dsonar.web.javaAdditionalOpts="$SONARQUBE_WEB_JVM_OPTS -Djava.security.egd=file:/dev/./urandom" \ 17 | "$@" -------------------------------------------------------------------------------- /content/articles/sync/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 说明 3 | --- 4 | 内容均来自[OSC_梦朝思夕博客](https://my.oschina.net/u/553243),[51CTO_梦朝思夕博客](http://blog.51cto.com/qiangmzsx) 5 | 6 | -------------------------------------------------------------------------------- /content/articles/sync/sync_once_source_code_analysis.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: sync.Once源码分析 3 | date: 2018-09-08T00:00:00+08:00 4 | --- 5 | sync.Once可以实现单例模式,确保sync.Once.Do(f func())只会被执行一次,可以初始化某个实例单例。 6 | 7 | 针对Golang 1.9的sync.Once,与Golang 1.10一样。 源代码位置:sync\once.go。 8 | 9 | ## 结构体 10 | Once结构体定义如下: 11 | ```go 12 | type Once struct { 13 | m Mutex 14 | done uint32 // 初始值为0表示还未执行过,1表示已经执行过 15 | } 16 | ``` 17 | 18 | ## Do 19 | ```go 20 | func (o *Once) Do(f func()) { 21 | // done==1表示已经执行过了,直接结束返回 22 | if atomic.LoadUint32(&o.done) == 1 { 23 | return 24 | } 25 | // 锁住对象,避免并发问题 26 | o.m.Lock() 27 | defer o.m.Unlock() 28 | if o.done == 0 { 29 | // 执行f函数后将done设置为1 30 | defer atomic.StoreUint32(&o.done, 1) 31 | f() 32 | } 33 | } 34 | ``` 35 | 36 | 需要注意的是执行f函数是同步进行的,也就是说可能存在阻塞问题。 37 | 38 | -------------------------------------------------------------------------------- /content/discuss/2018-05-09-wechat-discuss.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2018-05-09 微信群讨论 3 | date: 2018-05-09T00:00:00+08:00 4 | --- 5 | 6 | 来源:『Go 夜读』微信群 7 | 时间:2018-05-09 8 | 9 | ## 1. debug 10 | 11 | 调试:dlv 12 | 13 | (待补充) 14 | 15 | ## 2. not reached 16 | 17 | *go/src/runtime/panic.go* 18 | 19 | (待补充) 20 | 21 | ## 3. Go 开发工具 22 | 23 | - Vim:(待补充) 24 | - Emacs 25 | - VSCode 26 | - JetBrains: IntelliJ,Goland 27 | 28 | - Goland用学生邮箱可以免费 29 | - 服务器认证(这个就不贴了,大家自行Google) 30 | - [其他更多](https://www.jetbrains.com/go/buy/#edition=discounts) 31 | 32 |  33 |  34 | 35 | - LiteIDE: LiteIDE的跟踪代码很不错,可以同时在一个窗口打开多个项目的目录. 36 | 37 | ## 4. 问题 38 | 39 | ``` 40 | var x string 41 | func init() { 42 | x, err := getValue() 43 | } 44 | ``` 45 | 46 | 有一个全局变量 x,在 `init()` 函数里面赋值,然后获取 x 的值发现全局变量未赋值,这种情况有什么优雅的解决方法吗? 47 | 48 | ```go 49 | var x string 50 | func init() { 51 | var err error 52 | x, err = getValue() 53 | } 54 | ``` 55 | 56 | 这个:=为什么不能对全局变量起作用呢?因为它成为局部变量了,屏蔽了全局变量作用域。 57 | 58 | ```go 59 | var x string 60 | func init()(err error) { 61 | x, err = getValue() 62 | } 63 | ``` 64 | 65 | 以上代码是 **错误** 的,Go 语言中 main() 和 init() 函数都不能有返回值,否则编译会报错: 66 | 67 | ```go 68 | func init must have no arguments and no return values 69 | func main must have no arguments and no return values 70 | ``` 71 | 72 | ## 参考资料 73 | 74 | 1. [Go 开发工具](https://github.com/yangwenmai/learning-golang#go-开发工具) -------------------------------------------------------------------------------- /content/discuss/2018-05-10-which-vendor-tool.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2018-05-10 用什么工具解决项目依赖 3 | date: 2018-05-10T00:00:00+08:00 4 | --- 5 | 来源:『Go 夜读』微信群 6 | 时间:2018-05-10 13:30 7 | 8 | ## 1. 你们是用什么工具解决项目依赖的呢? 9 | 10 | - [dep](https://github.com/golang/dep) 11 | - govendor 12 | 13 | govendor 最简洁,glide最方便,不过一般团队用啥就用啥。 14 | 15 | ## 2. 平时你们的工作目录结果是怎样的? 16 | 17 | - *一个大的 GOPATH 下,放所有项目*【比较多是这种方式】 18 | - 一个项目一个 GOPATH 19 | - 有一个默认 GOPATH,不同项目有不同的 GOPATH 20 | 21 | VisualStudio Code 的设置: `"go.gopath": "${workspaceRoot}:/Users/username/gopath"` 22 | 公共第三方包是公用的,每个有自己的 vendor,编译打包什么的都是各自的 makefile(很多Github上的大项目,比如docker,都是自己写 Makefile ,整理项目依赖,没有一个统一的形式) 23 | 24 | Rust 的项目结构比 Go 好,Rust 的 cargo 还不错。 25 | 26 | - 可以给 GOPATH 写一个脚本 27 | 28 | ```shell 29 | gop() { 30 | if [ "$1" = "" ]; then 31 | elif [ "$1" = "d" ]; then 32 | export GOPATH=`echo $DEF_GOPATH` 33 | elif [ "$1" = "a" ]; then 34 | export GOPATH=`echo $DEF_GOPATH`:`pwd` 35 | elif [ "$1" = "f" ]; then 36 | export GOPATH=`pwd` 37 | fi 38 | 39 | echo "current GOPATH = "$GOPATH 40 | } 41 | ``` 42 | 43 | ## 参考资料 44 | 45 | 1. [Go Vendoring Tools 使用总结](http://researchlab.github.io/2016/05/24/comparison-of-Go-Vendoring-Tools/) 46 | 2. [Golang 代码规范](https://sheepbao.github.io/post/golang_code_specification/) -------------------------------------------------------------------------------- /content/discuss/2018-05-16-the-way-to-go.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2018-05-16 Go 学习之路 3 | date: 2018-05-16T00:00:00+08:00 4 | --- 5 | 来源:『Go 夜读』微信群 6 | 时间:2018-05-16 7 | 8 | ---- 9 | 10 | >推荐新手先看一看[Go 学习之路](https://github.com/talkgo/read) 11 | 12 | ## 1. 有没有适合小白看的项目?(没有底层语言基础) 13 | 14 | - 建议先系统过一遍基础语法; 15 | - 看了 Go 基础之后,可以把数据结构,排序:树、表等都撸一遍; 16 | - 自己写点工具、爬虫之类的进步比较快; 17 | - 推荐『Go 语言实战』,[『Go 语言系列』](http://mp.weixin.qq.com/mp/homepage?__biz=MzI3MjU4Njk3Ng==&hid=1&sn=eded6298ac9958f525935a24020974bb&scene=1&devicetype=android-23&version=26060637&lang=zh_CN&nettype=WIFI&ascene=7&session_us=gh_a618995bd9c9&from=groupmessage&isappinstalled=0),适合从入门到深入 18 | - [编程书籍的整理和收集](https://github.com/KeKe-Li/book) 19 | - 雨痕大神些的『Go 语言学习笔记』也不错,包含语法介绍和源码剖析(可能不适合初学者哦,比较多的底层知识) 20 | 21 | **推荐项目** 22 | 23 | - beego 24 | - BoltDB(不维护了,但是代码不多,注释比较详细,作为学习容易入门) 25 | - [urfave/cli](https://github.com/urfave/cli) 26 | - [grpc-gateway](https://github.com/grpc-ecosystem/grpc-gateway) 27 | - [grpc-go](https://github.com/grpc/grpc-go) 28 | 29 | -------------------------------------------------------------------------------- /content/discuss/2018-05-23-wechat-discuss.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2018-05-23 Get passes lock by value 3 | date: 2018-05-23T00:00:00+08:00 4 | --- 5 | 来源:『Go 夜读』微信群 6 | 7 | 时间:2018-05-23 8 | 9 | ---- 10 | 11 | ## 1. Get passes lock by value 12 | 13 | ```go 14 | type ExecuterList struct { 15 | sync.Map 16 | length int 17 | } 18 | 19 | func (e ExecuterList) Get(key string) IExecuter { 20 | value, ok := e.Load(key) 21 | if !ok { 22 | return nil 23 | } 24 | if value == nil { 25 | return nil 26 | } 27 | res, _ := value.(IExecuter) 28 | return res 29 | } 30 | ``` 31 | 32 | 使用 `go tool vet` ,出现“Get passes lock by value: ExecuterList contains sync.Map contains sync.Mutex”, 解决方案有两种:。 33 | 34 | 1,sync.Map用指针 35 | 36 | ```go 37 | type X struct { 38 | *sync.Map 39 | } 40 | ``` 41 | 42 | 2, 也可以用 `(e *ExecutorList)` ,避免锁的复制。 43 | 44 | 为什么会失效呢? 45 | 46 | >因为你每次操作都复制了一遍整个struct,当然也复制了Map里面的Mutex,多线程同时读写时Map里面的锁相当于失效了。理解这个你需要知道的知识点有两个,一是go的参数都是值传递,二是只有用同一把锁才能对某个资源边界进行锁与解锁的操作。 47 | 48 | ## 2. RPC 微服务框架 49 | 50 | rpc 可以封装程序间网络通信层,服务间调用只需要关注目标服务是什么,不用关心我到底用什么协议和数据格式了。 51 | 52 | [为什么我推荐避免使用 go-kit 库?](https://gist.github.com/posener/330c2b08aaefdea6f900ff0543773b2e) 53 | -------------------------------------------------------------------------------- /content/discuss/2018-06-07-dial-timeout-in-go.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2018-06-07 Dial 超时 3 | date: 2018-06-07T00:00:00+08:00 4 | --- 5 | 来源:『Go 夜读』微信群 6 | 7 | 时间:2018-06-07 8 | 9 | ---- 10 | 11 | ## 问题1 12 | 13 | ```go 14 | func DialTCP(network string, laddr, raddr *TCPAddr) (*TCPConn, error) { 15 | func DialTimeout(network, address string, timeout time.Duration) (Conn, error) { 16 | ``` 17 | 18 | 这两个方法返回的对象类型不一样,想得到TCPConn对象,同时可以设置连接超时,应该怎么写?有谁可以帮帮忙吗? 19 | 20 | 回答: 21 | 22 | Use [`net.Dialer`](https://godoc.org/net#Dialer) with either the [Timeout](https://godoc.org/net#Dialer.Timeout) or [Deadline](https://godoc.org/net#Dialer.Deadline) fields set. 23 | 24 | ```go 25 | d := net.Dialer{Timeout: timeout} 26 | conn, err := d.Dial("tcp", addr) 27 | if err != nil { 28 | // handle error 29 | } 30 | ``` 31 | 32 | A variation is to call [`Dialer.DialContext`](https://godoc.org/net#Dialer.DialContext) with a [deadline](https://godoc.org/context#WithDeadline) or [timeout](https://godoc.org/context#WithTimeout) applied to the context. 33 | 34 | Type assert to `*net.TCPConn` if you specifically need that type instead of a `net.Conn`: 35 | 36 | ```go 37 | tcpConn, ok := conn.(*net.TCPConn) 38 | ``` 39 | 40 | ## 参考资料 41 | 42 | 1. [https://stackoverflow.com/questions/47117850/how-to-set-timeout-while-doing-a-net-dialtcp-in-golang](https://stackoverflow.com/questions/47117850/how-to-set-timeout-while-doing-a-net-dialtcp-in-golang) 43 | -------------------------------------------------------------------------------- /content/discuss/2018-07-04-package-names.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2018-07-04 文件夹命名 3 | date: 2018-07-04T00:00:00+08:00 4 | --- 5 | 来源:『Go 夜读』微信群 6 | 7 | 时间:2018-07-04 8 | 9 | ---- 10 | 11 | ## 问题1. 话说大家 go 文件夹命名 是什么规范。下划线 横线 驼峰?有标准么? 12 | 13 | 有标准 [https://blog.golang.org/package-names](https://blog.golang.org/package-names) 14 | 15 | ## 问题2. 包的命名多个单词的情况呢? 16 | 17 | 包名和文件名用小写,使用短命名,尽量和标准库不要冲突。 18 | 19 | 文件名或者文件夹不要用大写,切记!!! 20 | 21 | >系统有些区别大小写,有些不区分,比如 Mac 不区分大小写,而 linux 区分。 22 | 23 | >制作规范的时候参考的是 effective go。 24 | 25 | ---- 26 | 27 | ## 参考 28 | 29 | * [Golang 代码规范](https://sheepbao.github.io/post/golang_code_specification/) 30 | -------------------------------------------------------------------------------- /content/discuss/2018-07-14-version-gopath-go-command.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2018-07-14 包版本管理 3 | date: 2018-07-14T00:00:00+08:00 4 | --- 5 | 来源:『Go 夜读』微信群 6 | 7 | 时间:2018-07-14 8 | 9 | ---- 10 | 11 | ## 问题1:包版本管理? 12 | 13 | govendor,vgo? 14 | 15 | vgo 是 Go Module 的前身。 16 | 17 | ## 问题2:为什么要搞一个 GOPATH ? 18 | 19 | GOPATH 是 Go 最初设计的产物,在 Go 语言快速发展的今天,人们日益发现 GOPATH 似乎不那么重要了,尤其是在引入 vendor 以及诸多包管理工具后。并且 GOPATH 的设置还会让 Go 语言新手感到些许困惑,提高了入门的门槛。Go core team 也一直在寻求 “去 GOPATH” 的方案,当然这一过程是循序渐进的。Go 1.8 版本中,如果开发者没有显式设置 GOPATH,Go 会赋予 GOPATH 一个默认值(在 linux 上为 $HOME/go )。虽说不用再设置 GOPATH,但 GOPATH 还是事实存在的,它在 go toolchain 中依旧发挥着至关重要的作用。 20 | 21 | ## 问题3:go get 命令内部应该也是用 git clone 命令吧? 22 | 23 | https://github.com/golang/go/wiki/GoGetTools 24 | https://github.com/hyper0x/go_command_tutorial/blob/master/0.3.md 25 | 26 | ### 参考链接 27 | 28 | 1. https://github.com/golang/go/wiki/PackageManagementTools 29 | 2. [初窥 Go Module](https://mp.weixin.qq.com/s/ris9hYqRMKMX-HCZMpNMkg) 30 | 3. https://git-scm.com/docs/revisions 31 | 4. https://dave.cheney.net/2018/07/14/taking-go-modules-for-a-spin 32 | 33 | -------------------------------------------------------------------------------- /content/discuss/2018-08-14-wechat-discuss.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2018-08-14 做实时语音流,用什么来做比较好 3 | date: 2018-08-14T00:00:00+08:00 4 | --- 5 | 来源:『Go 夜读』微信群 6 | 7 | 时间:2018-08-14 8 | 9 | ### 问题:做实时语音流,用什么来做比较好?rtmp?还是ws? 10 | 11 | - 第三方:即构(推荐)、声网(自己做不稳定,还得搞流媒体服务器) 12 | - 自己做一般都是rtmp 13 | 14 | >实时?需要有多实时?直播还是点到点通信? 15 | >A:有一个实现是在 boya 的 rtmp 协议基础上,完善了 golang 的 rtmp 流媒体服务器,最近已经上网运行了,支持查询回源,定点回源等,资源消耗很低。也可参考项目[livego](https://github.com/gwuhaolin/livego) 16 | 17 | ### Go 默认使用 CPU 核数? 18 | 19 |  20 | 21 | 具体代码:`proc.go#schedinit()`。 22 | 23 | 文档说明:[runtime-GOMAXPROCS](https://golang.org/doc/go1.5#runtime) 24 | 25 | >Another potentially breaking change is that the runtime now sets the default number of threads to run simultaneously, defined by GOMAXPROCS, to the number of cores available on the CPU. In prior releases the default was 1. Programs that do not expect to run with multiple cores may break inadvertently. They can be updated by removing the restriction or by setting GOMAXPROCS explicitly. For a more detailed discussion of this change, see [the design document - Russ Cox](https://docs.google.com/document/d/1At2Ls5_fhJQ59kDK2DFVhFu3g5mATSXqqV5QrxinasI/edit). 26 | 27 | [discuss on golang-dev](https://groups.google.com/forum/#!msg/golang-dev/POSw7qrelso/dI3YPTeGbkMJ) 28 | 29 | ### etcd 30 | 31 | etcd 心跳超时是 1s ; 32 | etcd 用了[raft 分布式一致性算法](http://thesecretlivesofdata.com/raft)。 33 | 其他的内容有待后续整理。。。 34 | 35 | ## 参考 36 | 37 | 1. [Raft一致性算法论文](https://github.com/maemual/raft-zh_cn/blob/master/raft-zh_cn.md) 38 | 2. [分布式一致性算法:可能比你想象得更复杂](https://mp.weixin.qq.com/s/ohTXhFFywGHGDOkzO45aaQ) 39 | -------------------------------------------------------------------------------- /content/discuss/2018-08-15-wechat-discuss.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2018-08-15 深度 | 从 Go 高性能日志库 zap 看如何实现高性能 Go 组件 3 | date: 2018-08-15T00:00:00+08:00 4 | --- 5 | 来源:『Go 夜读』微信群 6 | 7 | 时间:2018-08-15 8 | 9 | ### 深度 | 从 Go 高性能日志库 zap 看如何实现高性能 Go 组件 10 | 11 | >一篇技术文章引发的讨论。 12 | 13 | - 我们有一个服务用 logrus 落日志,并发量太高了,直接影响了性能。 14 | - printf 类型字符串格式化的日志格式,不再推荐,现在日志的消费,逐渐从人转向了计算机,结构化的数据和友好的解析方式更重要。---跟 logrus 的作者观点一样,“核心不是性能”。。。 15 |  16 | 17 | - 我们后面也用 sync.Pool 去优化落日志这一块。(当时因为 logrus 写日志这一块,直接在高并发的时候多开销了10G内存,当时服务总共开销才 15 G内存。后面做了一些优化,用 sync.Pool 提前把日志格式化好,不是用 logrus 里面的 WithFields 之类的,后来对比过 zerolog,但是优化后在 3W 左右的日志并发时,从我们服务器的监控来看,整体没有太大的区别(内存、CPU、服务器的整体速度),所以后面也没有更换 log 库。(原因是在于替换成本也比较高。)) 18 |  19 | 20 | ### Echo 里面的 context 也是用 sync.Pool 解决高并发的时候内存占用问题 21 | 22 | sync.Pool 的定位不是做类似于连接池的东西,它的用途仅仅是增加对象重用的几率,减少 gc 的负担,而开销方面也不是很便宜的。 23 | 24 | [sync.Pool](https://golang.org/pkg/sync/#Pool) 本来就是当做 cache 用的,在 Go 官方文档上已经明确说明了,数据不能保存在 pool 里面,有可能会遇到 GC 回收。 25 | >A Pool is a set of temporary objects that may be individually saved and retrieved. 26 | 27 | >Any item stored in the Pool may be removed automatically at any time without notification. If the Pool holds the only reference when this happens, the item might be deallocated. 28 | 29 | ## 参考 30 | 31 | 1. [深度 | 从 Go 高性能日志库 zap 看如何实现高性能 Go 组件](https://mp.weixin.qq.com/s/i0bMh_gLLrdnhAEWlF-xDw) 32 | 2. [kingsoft-wps-log4go](https://github.com/kingsoft-wps/log4go) 33 | 3. [go语言的官方包sync.Pool的实现原理和适用场景](https://blog.csdn.net/yongjian_lian/article/details/42058893) 34 | 4. [大幅提升 golang 写日志序列化性能实践](https://my.oschina.net/u/2950272/blog/1785808) 35 | -------------------------------------------------------------------------------- /content/discuss/2018-08-23-wechat-discuss.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2018-08-23 有什么好的博客平台吗 3 | date: 2018-08-23T00:00:00+08:00 4 | --- 5 | 来源:『Go 夜读』微信群 6 | 7 | 时间:2018-08-23 8 | 9 | ### 有什么好的博客平台吗?(除了简书) 10 | 11 | - Github pages 12 | - hugo + Github 13 | - 自建 14 | - jekyll 15 | - Ghost 16 | - hexo + Github 17 | - hexo + Coding pages 18 | 19 | 图片CDN:七牛 20 | 21 | ### 请问nats有类似[kafka manager](https://github.com/yahoo/kafka-manager)这样的管理后台吗? 22 | 23 | - kafka manager 的管理后台:kafkatool 24 | 25 | ### 对kafka的抽象 26 | 27 |  28 | 29 | kafka聚焦于数据管道,nats聚焦于message bus 30 | 31 | ### for-select ? 32 | 33 | 下面这段代码为什么运行一会儿就停止了呢? 34 | 35 |  36 | 37 | 用 waitgroup 肯定是正常的,研究一个 go sceduler 的问题,所以才故意这样写的。 38 | 39 | for {}这种死循环(现实中应该用不着,反正我没用过这种需求),编译的时候不会被go插入抢占的代码(morestack 函数),导致调度切换不出去。这个问题go团队已经在着手解决了 [golang/go/issues#24543](https://github.com/golang/go/issues/24543),不理解的话,可以看看:[](https://tonybai.com/2017/11/23/the-simple-analysis-of-goroutine-schedule-examples/) 40 | 41 | 加打印会有系统调用,就会插入调度抢占代码,抢占调度的前提是需要插入morestackt代码,和编译器和调度机制都有关系。。 42 | 43 | go 中加入 spinning threads 的目的是啥,有相关资料吗? 44 | >让 M 工作。 45 | 46 |  47 | 48 | spin 和 unspin 对应就是 M 运行和休眠的状态,也就是线程运行和休眠的状态,M 只有实在找不多 G 来做的时候才会休眠。 49 | 50 | ## 参考 51 | 52 | 1. [系统设计入门](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md) 53 | 2. [https://stackshare.io/stackups/kafka-vs-nsq-vs-rabbitmq](https://stackshare.io/stackups/kafka-vs-nsq-vs-rabbitmq) 54 | 3. [https://github.com/golang/go/issues/15442](https://github.com/golang/go/issues/15442) 55 | 4. [https://rakyll.org/scheduler/](https://rakyll.org/scheduler/) 56 | 57 | -------------------------------------------------------------------------------- /content/discuss/2018-08-24-wechat-discuss.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2018-08-24 工具推荐 3 | date: 2018-08-24T00:00:00+08:00 4 | --- 5 | 来源:『Go 夜读』微信群 6 | 7 | 时间:2018-08-24 8 | 9 | ### 工具推荐 10 | 11 | 1. [SequelPro(MySQL Client GUI)](https://www.sequelpro.com/) 12 | 2. [Robot 3T(MongoDB Client GUI)](https://robomongo.org/) 13 | 3. [mycli(MySQL command line client)](https://www.mycli.net/) 14 | 4. [Navicat Premium(DB Client GUI)](https://www.navicat.com/en/products/navicat-premium) 15 | 5. [DataGrip: Database management systems by JetBrains](https://www.jetbrains.com/datagrip/) 16 | 6. [SQLyog is an all-round Management Tool (/'GUI'/'Frontend') for MySQL](https://www.webyog.com/) 17 | -------------------------------------------------------------------------------- /content/discuss/2018-09-04-wechat-discuss.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2018-09-04 微信讨论 3 | date: 2018-09-04T00:00:00+08:00 4 | --- 5 | 来源:『Go 夜读』微信群 6 | 7 | ### Request Body 的请求中,不能 bind 两次吗? 8 | 9 | ```golang 10 | var body struct { 11 | Fcid string "fcid" 12 | } 13 | c.Bind(&body) 14 | log.Traceln("body", body) 15 | var body2 struct { 16 | Fcid string "fcid" 17 | } 18 | c.Bind(&body2) 19 | log.Traceln("body2", body2) 20 | ``` 21 | 22 | 打印输出结果为: 23 | 24 | ```sh 25 | 2018/09/04 14:58:44.641654 [TRC] jwtValidator.go:34: body {@sign-test2} 26 | 2018/09/04 14:58:44.641674 [TRC] jwtValidator.go:41: body2: {} 27 | ``` 28 | 29 | >Body 不是 is.Seeker 无法 seek,应该不能重复 bind 的。 30 | 31 |  32 | 33 | ### protobuf 3 枚举第一个必须是0,但是用的时候,用第一个 struct 会是空 34 | 35 | ```golang 36 | log.Println(protocol.RESULT_CODE) 37 | xxx := &protocol.XResp{ 38 | Result: protocol.RESULT_CODE, 39 | } 40 | log.Println(xxx) 41 | 42 | // OUTPUT: 43 | // 2018-09-06 09:06:00.111 [d] CODE 44 | // 2018-09-06 09:06:00.111 [d] 45 | ``` 46 | 47 | 第一位是占位用的。 48 | 49 | ## 参考资料 50 | 51 | - [Enum value with index 0 not shown #3808](https://github.com/protocolbuffers/protobuf/issues/3808) 52 | - [proto3#enum](https://developers.google.com/protocol-buffers/docs/proto3#enum) 53 | - [In Go, how can I reuse a ReadCloser?](https://stackoverflow.com/questions/33532374/in-go-how-can-i-reuse-a-readcloser) 54 | -------------------------------------------------------------------------------- /content/discuss/2018-09-18-benchmark-tools.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2018-09-18 压测接口性能的框架,大家有没有推荐 3 | date: 2018-09-18T00:00:00+08:00 4 | --- 5 | 来源:『Go 夜读』微信群 6 | 7 | ### 压测接口性能的框架,大家有没有推荐? 8 | 9 | - [wrk](https://github.com/wg/wrk) 10 | - [hey](https://github.com/rakyll/hey) 11 | - [vegeta](https://github.com/tsenart/vegeta) 12 | -------------------------------------------------------------------------------- /content/discuss/2018-10-18-encOp.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2018-10-18 encOp 是在哪里实现的呢? 3 | date: 2018-10-18T00:00:00+08:00 4 | --- 5 | 来源: Wechat discuss 6 | 7 | ## encOp 是在哪里实现的呢? 8 | 9 | >encode.go文件中的这行代码是对数据进行编码么,具体怎么实现的,在哪里知道么? 10 | instr.op(instr, state, reflect.Value{}) 11 | 12 | ```golang 13 | func (enc *Encoder) encode(b *encBuffer, value reflect.Value, ut *userTypeInfo) { 14 | defer catchError(&enc.err) 15 | engine := getEncEngine(ut, nil) 16 | ... 17 | } 18 | ``` 19 | 20 | 点击进入 `getEncEngine` -> `buildEncEngine` -> `compileEnc` -> `encOpFor` 21 | 22 | ```golang 23 | func encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp, building map[*typeInfo]bool) (*encOp, int) { 24 | ... 25 | var op encOp 26 | if int(k) < len(encOpTable) { 27 | op = encOpTable[k] 28 | } 29 | ... 30 | } 31 | ... 32 | var encOpTable = [...]encOp{ 33 | reflect.Bool: encBool, 34 | reflect.Int: encInt, 35 | reflect.Int8: encInt, 36 | reflect.Int16: encInt, 37 | reflect.Int32: encInt, 38 | reflect.Int64: encInt, 39 | reflect.Uint: encUint, 40 | reflect.Uint8: encUint, 41 | reflect.Uint16: encUint, 42 | reflect.Uint32: encUint, 43 | reflect.Uint64: encUint, 44 | reflect.Uintptr: encUint, 45 | reflect.Float32: encFloat, 46 | reflect.Float64: encFloat, 47 | reflect.Complex64: encComplex, 48 | reflect.Complex128: encComplex, 49 | reflect.String: encString, 50 | } 51 | ``` 52 | 53 | 点击每个 value 就可以查看其实现了。 54 | -------------------------------------------------------------------------------- /content/discuss/2018-11-08-aws-ec2-ssh-login-problem.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2018-11-08 aws ec2实例无法连接登录问题 3 | date: 2018-11-08T00:00:00+08:00 4 | --- 5 | 来源:『Go 夜读』微信群 6 | 7 | 时间:2018-11-08 8 | 9 | --- 10 | 11 | ## aws ec2实例无法连接登录问题 12 | 13 | 在AWS上注册一个账号,然后创建一个免费试用期限的虚拟机,虚拟机成功创建并启动之后,我们通过SSH登录这台虚拟机出现无法连接的问题. 14 | 15 | 连接方式aws console页面会提示你如何连接,如下: 16 | 17 | ```bash 18 | # 1. 创建虚拟机的时候会让你生成一个pem秘钥文件作为登录认证,把这个xxx.pem文件放到自己的机器上并设置400权限 19 | chmod 400 wpc-secret.pem 20 | 21 | # 2. 登录(注意我的是aws虚拟机是centos系统需要ec2-user用户登录,加-v参数显示登录过程详细信息) 22 | ssh -i "wpc-secret.pem" ec2-user@ec2-18-224-136-148.us-east-2.compute.amazonaws.com -v 23 | 24 | # 3. 我们会发现无法登录,超时登录后断开了,是因为默认ec2上面创建的虚拟机在默认情况下,默认安全组不允许传入SSH流量。所以你需要在ec2 console中的左侧菜单栏找到安全组然后添加SSH类型的入站和出站规则即可 25 | 略... 26 | 27 | # 4. 重新尝试登录,一般情况先就成功登录上了 28 | ssh -i "wpc-secret.pem" ec2-user@ec2-18-224-136-148.us-east-2.compute.amazonaws.com -v 29 | ... 30 | ``` 31 | -------------------------------------------------------------------------------- /content/discuss/2018-11-09-force-to-use-keyed-struct-literals.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2018-11-09 强制使用字段命名方式初始化结构体 3 | date: 2018-11-09T00:00:00+08:00 4 | --- 5 | 来源:『Go 夜读』微信群 6 | 7 | 时间:2018-11-09 8 | 9 | --- 10 | 11 | ## 强制使用字段命名方式初始化结构体 12 | 13 | 在定义结构体时,加入一个非导出且大小为0的字段, 编译器会强制开发者使用字段命名的方式初始化结构体, 而不能按顺序来赋值. 14 | 15 | `这个小技巧利用了包的非导出字段可见性, 所以只能在不同包下初始化结构体才有用.` 16 | 17 | ```golang 18 | // foo.go 19 | package foo 20 | 21 | type Config struct { 22 | _ [0]int 23 | Name string 24 | Size int 25 | } 26 | ``` 27 | 28 | ```golang 29 | // main.go 30 | package main 31 | 32 | import "foo" 33 | 34 | func main() { 35 | //_ = foo.Config{[0]int{}, "bar", 123} 36 | // doesn't compile 37 | // 报错信息:implicit assignment of unexported field 'flag' in foo.Config literal 38 | 39 | _ = foo.Config{Name: "bar", Size: 123} // compile okay 40 | } 41 | ``` 42 | 43 | >不要把非导出且大小为0的字段放在结构体的最后面, 可能会导致多分配内存. 44 | 45 | ## 参考资料 46 | 47 | 1. [How to force package users to use struct composite literals with field names?](https://go101.org/article/tips.html#force-to-use-keyed-struct-literals) 48 | 2. [Why does the final field of a zero-sized type in a struct contribute to the size of the struct sometimes?](https://go101.org/article/unofficial-faq.html#final-zero-size-field) 49 | 3. [golang 内存分析之字节对齐规则](https://my.oschina.net/u/2950272/blog/1829197) -------------------------------------------------------------------------------- /content/discuss/2018-11-29-config-in-go.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Golang 用什么配置中心管理服务 3 | date: 2018-11-29T17:13:46+08:00 4 | --- 5 | 来源:『Go 夜读』微信群 6 | 7 | 时间:2018-11-29 8 | 9 | --- 10 | 11 | ## Golang 用什么配置中心管理服务? 12 | 13 | - etcd 14 | 15 | >https://juejin.im/post/5b7e8b82f265da432e75c7c4 16 | 17 | - Qconf 18 | -------------------------------------------------------------------------------- /content/discuss/2018-12-04-change-to-go.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 实打实的 Go 项目,但是 Github 却统计为 JavaScript 怎么办? 3 | date: 2018-12-04T17:13:46+08:00 4 | --- 5 | 来源:『Go 夜读』微信群 6 | 7 | 时间:2018-12-04 8 | 9 | --- 10 | 11 | ## 原理 12 | 13 | Github 采用 Linguist 来自动识别你的代码,然后判断属于哪一种语言。 14 | 15 | ## 问题 16 | 17 | 但是我是一个 Go 相关的文档或者 Go Web 工程项目,肯定希望在搜索 Go 语言的时候,也能包括我,并且显示项目所属语言为 Go。 18 | 19 | 但是默认情况下,你肯定会失望。。。可能还会吐槽:为什么 Github 不提供一个选择项目所属语言呢? 20 | 21 | >针对这个问题,我的思考是,Github 就是想让大家 hack 一点。 22 | 23 | ## 解决方法 24 | 25 | 1. 在项目中增加更多的你所想要归属的语言的代码(综合性项目,最好是采用这种方式)。 26 | 2. 在项目中添加 `.gitattributes` 27 | 28 | ```sh 29 | *.js linguist-language=go 30 | *.java linguist-language=go 31 | ... 32 | ``` 33 | 34 | 这种方式会导致你处理的后缀语言也不会在项目中被标识出来了。 35 | 36 | -------------------------------------------------------------------------------- /content/discuss/2018-12-07-wechat-discuss.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "2018-12-07 微信讨论" 3 | date: 2018-12-07T23:13:46+08:00 4 | --- 5 | 6 | 来源:『Go 夜读』微信群 7 | 8 | >应该还是负数问题,你实验一下 9 | 10 | 下面这种情况的负数报错是在 build 阶段报的: 11 | 12 | ```golang 13 | errMake := make([]byte, 64-22*5) // negative len argument in make([]byte) 14 | ``` 15 | 16 | 下面这种情况的负数,编译时不知道,是在运行时的报错: 17 | 18 | ```golang 19 | errMake := make([]byte, 64-len(testStr)*5) // runtime error: makeslice: len out of range 20 | ``` 21 | -------------------------------------------------------------------------------- /content/discuss/2018-12-25-macOS-time-synchronization.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2018-12-25 MacOS Time Synchronization 3 | date: 2018-12-25T16:36:45+08:00 4 | --- 5 | 来源: Wechat discuss 6 | 7 | ## MacOS Time Synchronization 8 | 9 | > 今天在启动 Geth (以太坊私链节点)的时候,出现了以下的错误。在比较后发现本机时间落后了北京时间近一分钟。 10 | 11 |  12 | 13 | 14 | > 在搜索解决方案的时候,发现在 macOS Mojave 里面 `ntpdate` 已经废弃了。 15 | > 改用了`sntp`,在Terminal输入以下的命令,即可同步。 16 | 17 | 18 | ```bash 19 | sudo sntp -sS time.asia.apple.com 20 | ``` 21 | 22 | ### 系统设置建议 23 | 24 |  25 | 26 | - 1、自动设置日期与时间 27 | - 2、时区不要自动设定,选择中国北京,因为不同地区的时间会有误差。 28 | 29 | 30 | ## 参考资料 31 | 32 | 1. https://apple.stackexchange.com/questions/117864/how-can-i-tell-if-my-mac-is-keeping-the-clock-updated-properly -------------------------------------------------------------------------------- /content/discuss/2019-02-20-bigdecimal-show-string.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2019-02-20 浮点数如何输出 3 | date: 2019-02-20T00:00:00+08:00 4 | --- 5 | 6 | 来源: Wechat discuss 7 | 8 | 9 | ### 将数据序列化为json的时候,怎么让序列化后的 json 里面不要使用科学计数法 10 | ### json.Marshal 转出来的json怎么能不让转成科学计数法 大家有解决办法吗? 11 | 12 | ```golang 13 | dec := decimal.NewFromFloat(0.000001) 14 | fmt.Println(dec.String()) 15 | ``` 16 | 17 | ## 参考资料 18 | 19 | 1. [shopspring/decimal](https://github.com/shopspring/decimal) 20 | -------------------------------------------------------------------------------- /content/discuss/2019-04-10-remove-local-branch-in-merged-master.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2019-04-10 3 | date: 2019-04-10T00:00:00+08:00 4 | --- 5 | 6 | 来源:『Go 夜读』微信群 7 | 8 | ## 本地开发分支已经 merge 到 master 后,如何快捷的删除本地开发分支? 9 | 10 | ``` 11 | #!/bin/bash 12 | 13 | function git_branch_cleanup() { 14 | for branch in `git branch --format='%(refname:short)'|grep -v '\*\|master'` ; do 15 | git checkout $branch 16 | check_results=`git fetch origin master && git rebase origin/master` 17 | result=$(echo $check_results | grep "up to date.") 18 | if [ "$result" == "" ];then 19 | echo "不包含 up to date. $check_results !\n" 20 | fi 21 | done 22 | git checkout master 23 | git branch --merged | grep -v '\*\|master' | xargs -n 1 git branch -d 24 | } 25 | 26 | git_branch_cleanup 27 | ``` 28 | 29 | 你可以将以上代码创建到 `/usr/local/bin/gcup`,这样你就可以在项目中使用 `gcup` 命令了。 30 | >注意:gcup 需要权限:`chmod +x gcup` 31 | >如果之前没有清理无用分支,可能会有大量冲突需要处理。 32 | 33 | 其他办法: 34 | 我们也可以遍历本地所有分支,然后排除一些白名单的分支,然后再把其他的全部删掉。 35 | >`git branch -d xxx` 能删掉的就都删掉了,如果你确定 xxx 分支没有用了,你也可以强制删除 `git branch -D xxx` 36 | 37 | 更简洁的代码:`git branch -d $(git branch -vv | grep ': gone\]' | awk '{print $1}')` -------------------------------------------------------------------------------- /content/discuss/2019-05-21-chromedp.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 2019-05-21 浏览器自动化工具 3 | date: 2019-05-21T00:00:00+08:00 4 | --- 5 | 6 | 来源:『Go 夜读』微信群 7 | 8 | ---- 9 | 10 | A0: chromedp 浏览器自动化工具,还有 puppeteer。 11 | 12 | A1: chromedp 不如 github.com/raff/godet 13 | chromedp 到现在都没把 chrome console 的功能实现 14 | 我们做 cookie scanner 的时候把相关的chrome driver 库用了个遍。 15 | 我们这里已经都测过了 https://github.com/CovenantSQL/CookieScanner 16 | 17 | A2: puppeteer 很好啊 18 | A3: chromedp 用起来比较难受,特别是部署的时候 19 | 20 | 如果用 Docker 不知道怎么搞呢? 21 | >zenika/alpine-chrome 可以用这个。 22 | 23 | 24 | 25 | 26 | ---- 27 | 28 | 未梳理,只是讨论纪要。 -------------------------------------------------------------------------------- /content/discuss/2019-10-13-go-module-looping-package.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: go mod下出现looping trying to add package 3 | date: 2019-10-13T12:12:00+08:00 4 | --- 5 | 来源:『Go 夜读』微信群 6 | 7 | 时间:2019-10-13 8 | 9 | --- 10 | 11 | ## 问题 12 | 13 | 忽然之间出现looping trying to add package 14 | 15 | 意思就是循环引用某个类库,提示如下: 16 | 17 | ```text 18 | 19 | go: github.com/sirupsen/logrus imports 20 | golang.org/x/sys/unix: looping trying to add package 21 | 22 | ``` 23 | 24 | ## 解决方法 25 | 26 | 删除go mod下的缓存,重新引用。 27 | 28 | ```shell 29 | 30 | sudo rm -fr "$(go env GOPATH)/pkg/mod" 31 | 32 | ``` 33 | 34 | [参考](https://github.com/rancher/k3s/issues/315) 35 | 36 | ```text 37 | 38 | sudo rm -fr "$(go env GOPATH)/pkg/mod” 39 | go get github.com/rancher/k3s@v.14.1-k3s.1 40 | After going through a screenful of dependencies, the program aborts with following error. 41 | .... 42 | .... 43 | go: downloading github.com/rancher/k3s v1.14.1-k3s.1 44 | go: finding github.com/rancher/k3s v0.3.0 45 | go: downloading github.com/rancher/k3s v0.3.0 46 | go: import "github.com/rancher/k3s": looping trying to add package 47 | 48 | ``` 49 | -------------------------------------------------------------------------------- /content/discuss/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "夜读讨论" 3 | date: 2018-11-15T12:32:37+08:00 4 | weight: 5 5 | --- 6 | -------------------------------------------------------------------------------- /content/discuss/log_color_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | // TestLogColor 测试日志颜色 9 | func TestLogColor(t *testing.T) { 10 | fmt.Println("") 11 | 12 | // | 前景 | 背景 | 颜色 | 13 | // |----|----|----| 14 | // | 30 | 40 | 黑色 | 15 | // | 31 | 41 | 红色 | 16 | // | 33 | 42 | 绿色 | 17 | // | 33 | 43 | 黄色 | 18 | // | 34 | 44 | 蓝色 | 19 | // | 35 | 45 | 紫红色 | 20 | // | 36 | 46 | 青蓝色 | 21 | // | 37 | 47 | 白色 | 22 | // 23 | // | 代码 | 意义 | 24 | // |----|----| 25 | // | 0 | 终端默认设置 | 26 | // | 1 | 高亮显示 | 27 | // | 4 | 使用下划线 | 28 | // | 5 | 闪烁 | 29 | // | 7 | 反白显示 | 30 | // | 8 | 不可见 | 31 | 32 | for b := 40; b <= 47; b++ { 33 | for f := 30; f <= 37; f++ { 34 | for d := range []int{0, 1, 4, 5, 7, 8} { 35 | fmt.Printf(" %c[%d;%d;%dm%s(f=%d,b=%d,d=%d)%c[0m ", 0x1B, d, b, f, "", f, b, d, 0x1B) 36 | } 37 | fmt.Println("") 38 | } 39 | fmt.Println("") 40 | } 41 | // 其中 0x1B 是标记,[开始定义颜色,1代表高亮,40代表黑色背景,32代表绿色前景色,0代表恢复默认颜色。 42 | fmt.Printf("%c[1;40;32m%s%c[0m", 0x1B, "testPrintColor", 0x1B) 43 | fmt.Println() 44 | fmt.Printf("%s\n", "testPrintColor") 45 | } 46 | -------------------------------------------------------------------------------- /content/harvest/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "你的收获" 3 | date: 2019-01-10T11:00:00+08:00 4 | weight: 8 5 | --- 6 | -------------------------------------------------------------------------------- /content/interview/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "面试专题" 3 | date: 2018-11-15T12:32:37+08:00 4 | weight: 7 5 | --- 6 | -------------------------------------------------------------------------------- /content/interview/interview-data-structure.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 数据结构 3 | date: 2018-07-26T00:00:00+08:00 4 | --- 5 | _1.什么是跳跃表?_ 6 | 7 | > 跳跃表是基于有序链表的一种扩展 8 | > 9 | > [查看资料](http://blog.jobbole.com/111731/) 10 | 11 | _2. 介绍下 RESTFull API 方式下, 怎么做到快速路由?_ 12 | 13 | > 一般使用前缀树/字典树, 来提高查找速度. 14 | 15 | > 开源的路由模块里, httprouter 是比较快的, 参考: https://github.com/julienschmidt/httprouter 16 | > 他使用了一种改进版的前缀树算法. 这个树的应用非常广泛, 除了做路由, 还有 linux 内核里使用, 在数据库里也有用到. 17 | > 参考文章: 18 | > 1. [路由查找之Radix Tree](https://michaelyou.github.io/2018/02/10/%E8%B7%AF%E7%94%B1%E6%9F%A5%E6%89%BE%E4%B9%8BRadix-Tree/) 19 | > 2. [图文详解Radix树](https://blog.csdn.net/petershina/article/details/53313624) 20 | > 3. [radix tree在数据库PostgreSQL中的一些应用举例](https://yq.aliyun.com/articles/75334) -------------------------------------------------------------------------------- /content/interview/interview-design.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 设计题 3 | date: 2018-07-26T00:00:00+08:00 4 | --- 5 | _1.要设计一个秒杀系统要注意什么?_ 6 | 7 |  8 | 9 | > **前端秒杀页面** 10 | > 11 | >> `页面静态化`:将活动页面上的所有可以静态的元素全部静态化,并尽量减少动态 12 | 元素。通过CDN来抗峰值。 13 | >> `禁止重复提交`:用户提交之后按钮置灰,禁止重复提交。 14 | >> `用户限流`:在某一时间段内只允许用户提交一次请求,比如可以采取IP限流。 15 | > 16 | > **服务端控制器(网关)** 17 | > 18 | >> `限制uid访问频率`:我们上面拦截了浏览器访问的请求,但针对某些恶意攻击或其它插件,在服务端控制层需要针对同一个访问uid,限制访问频率。 19 | > 20 | > **服务层** 21 | > 22 | >> `采用消息队列缓存请求`:既然服务层知道库存只有100台手机,那完全没有必要把100W个请求都传递到数据库啊,那么可以先把这些请求都写到消息队列缓存一下,数据库层订阅消息减库存,减库存成功的请求返回秒杀成功,失败的返回秒杀结束。 23 | >> `利用缓存应对读请求`:对类似于12306等购票业务,是典型的读多写少业务,大部分请求是查询请求,所以可以利用缓存分担数据库压力。 24 | >> `利用缓存应对写请求`:缓存也是可以应对写请求的,比如我们就可以把数据库中的库存数据转移到Redis缓存中,所有减库存操作都在Redis中进行,然后再通过后台进程把Redis中的用户秒杀请求同步到数据库中。 25 | > 26 | > **数据库层** 27 | > 28 | >> 数据库层是最脆弱的一层,一般在应用设计时在上游就需要把请求拦截掉,数据库层只承担“能力范围内”的访问请求。所以,上面通过在服务层引入队列和缓存,让最底层的数据库高枕无忧。 29 | 30 | _2.要设计一个类似微信红包架构系统要注意什么?_ 31 | 32 | > `南北分区` 33 | > `快慢分离` 34 | > `Hash负载均衡` 35 | > `Cache屏蔽DB` 36 | > `双维度分库表` 37 | > 38 | > [查看资料](https://blog.csdn.net/starsliu/article/details/51134473) -------------------------------------------------------------------------------- /content/interview/interview-network.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 网络 3 | date: 2018-07-26T00:00:00+08:00 4 | --- 5 | _1.tcp三次握手和四次挥手流程示意图?在黑板上画出_ 6 | 7 | > [查看资料](https://blog.csdn.net/smileiam/article/details/78226816) 8 | 9 | _2.客户端在建立异常中发现很多connect reset by peer,你觉得问题出在哪?_ 10 | 11 | > 三次握手维护的半连接队列或者全连接队列溢出导致 12 | > 13 | > [查看资料](https://mp.weixin.qq.com/s/yH3PzGEFopbpA-jw4MythQ) 14 | 15 | _3.https建立连接的过程?_ 16 | 17 |  18 | 19 | > 1.客户端发送请求到服务器端 20 | > 2.服务器端返回证书和公开密钥,公开密钥作为证书的一部分而存在 21 | > 3.客户端验证证书和公开密钥的有效性,如果有效,则生成对称密钥并使用公开密钥加密发送到服务器端 22 | > 4.服务器端使用私有密钥解密数据,并使用收到的对称密钥加密数据,发送到客户端 23 | > 5.客户端使用对称密钥解密数据 24 | > 6.SSL加密建立……… 25 | 26 | _4.tcp和udp的区别?_ 27 | 28 | > 1.TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前 29 | 不需要建立连接 30 | > 2.TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失, 31 | 不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付 32 | > 3.TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向 33 | 报文的,UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低 34 | > 4.每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的 35 | 交互通信 36 | > 5.TCP首部开销20字节;UDP的首部开销小,只有8个字节 37 | > 6.TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道 38 | 39 | _5.http,tcp,ip分别处于OSI哪一层?_ 40 | 41 | > `传输层协议`:TCP、UDP、SCTP 42 | > `网络层协议`:IP、ARP、RARP、ICMP、IGMP、OSPF 43 | > `应用层协议`:http,FTP、SMTP、RIP、DNS -------------------------------------------------------------------------------- /content/interview/interview-pen.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 笔试题 3 | date: 2018-07-26T00:00:00+08:00 4 | --- 5 | _1.Golang笔试题解析_ 6 | 7 | > [查看资料](https://blog.csdn.net/weiyuefei/article/details/77963810) -------------------------------------------------------------------------------- /content/night/1-2018-03-21-goutil.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第 1 期 2018-03-21 线下分享内容 3 | date: 2018-03-21T11:49:10+08:00 4 | --- 5 | >参与人数: 3 人 6 | 7 | ## cannot take address of temporary variables 8 | 9 | ## 延伸阅读 10 | 11 | - [https://stackoverflow.com/questions/10535743/address-of-a-temporary-in-go](https://stackoverflow.com/questions/10535743/address-of-a-temporary-in-go) 12 | - [https://stackoverflow.com/questions/40926479/take-the-address-of-a-character-in-string](https://stackoverflow.com/questions/40926479/take-the-address-of-a-character-in-string) 13 | - [https://golang.org/ref/spec#Address_operators](https://golang.org/ref/spec#Address_operators) 14 | 15 | ## neochain 16 | 17 | ## [teleport](https://github.com/henrylee2cn/teleport) 18 | 19 | Teleport 是一个通用、高效、灵活的Socket框架。 20 | 21 | 可用于 Peer-Peer 对等通信、RPC、长连接网关、微服务、推送服务,游戏服务等领域。 22 | 23 | ## [goutil](https://github.com/henrylee2cn/goutil) 24 | 25 | 通用的 Go 开发工具包 26 | 27 | - Calendar 28 | - CoarseTime 29 | - ... 30 | -------------------------------------------------------------------------------- /content/night/11-2018-07-26-golang-jenkins-sonarqube.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第 11 期 Golang 代码质量持续检测实践 3 | date: 2018-07-26T00:00:00+08:00 4 | --- 5 | 6 | ## 观看视频 7 | 8 | {{< youtube id="d95PZDAabqQ" >}} 9 | -------------------------------------------------------------------------------- /content/night/13-2018-08-09-kubernetes-guide.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: 由 genpost (https://github.com/hidevopsio/genpost) 代码生成器生成 3 | title: 第 13 期 Kubernetes 入门指南 4 | date: 2018-08-09T00:00:08+08:00 5 | author: 李森森 6 | --- 7 | 8 | ## 观看视频 9 | 10 | {{< youtube id="DJgYlmGCmDA" >}} -------------------------------------------------------------------------------- /content/night/14-2018-08-17-sync-pool-reading.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第 14 期 sync.Pool 源码分析及适用场景 3 | date: 2018-08-17T11:49:10+08:00 4 | --- 5 | 6 | *Go 标准包阅读* 7 | 8 | ## 观看视频 9 | 10 | {{< youtube id="jaepwn2PWPk" >}} -------------------------------------------------------------------------------- /content/night/17-2018-09-20-grpcp.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: 由 genpost (https://github.com/hidevopsio/genpost) 代码生成器生成 3 | title: 第 17 期 grpc 开发及 grpcp 的源码分析 4 | date: 2018-09-20T11:36:54+08:00 5 | author: 林益帆 6 | --- 7 | 8 | 9 | ## 观看视频 10 | 11 | {{< youtube id="sMBgYYEgm3c" >}} -------------------------------------------------------------------------------- /content/night/18-2018-09-27-CovenantSQL-DH-RPC.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: 由 genpost (https://github.com/hidevopsio/genpost) 代码生成器生成 3 | title: 第 18 期 去中心化加密通信框架 CovenantSQL/DH-RPC的设计 4 | date: 2018-09-27T11:19:54+08:00 5 | author: 王鹏程 6 | --- 7 | 8 | ## 观看视频 9 | 10 | {{< youtube id="bAfiKsLbDeE" >}} 11 | -------------------------------------------------------------------------------- /content/night/19-2018-11-08-http-router-in-go.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: 由 genpost (https://github.com/hidevopsio/genpost) 代码生成器生成 3 | title: 第 19 期 如何开发一个简单高性能的http router及gorouter源码分析 4 | date: 2018-11-08T11:49:10+08:00 5 | author: 徐佳军 6 | --- 7 | 8 | ## 观看视频 9 | 10 | {{< youtube id="3BoStxKECL0" >}} 11 | -------------------------------------------------------------------------------- /content/night/2-2018-04-11-teleport.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第 2 期 2018-04-11 线下分享内容 3 | date: 2018-04-11T11:49:10+08:00 4 | --- 5 | >参与人数: 9 人 6 | 7 | >微服务相关的开源项目,直接根据 Github 讲解,三个相关的项目链接如下: 8 | 9 | - [teleport是socket框架](https://github.com/henrylee2cn/teleport) 10 | - [tp-micro是它的扩展,实现了微服务](https://github.com/henrylee2cn/tp-micro) 11 | - [ants是该微服务的网关、配置中心、代码生成器、部署工具之类的](https://github.com/xiaoenai/ants) 12 | 13 | ---- 14 | 15 | ## 语音实录 16 | 17 | >以下内容是分享活动的实录回顾。 18 | 19 | 1. 参与人数: 9人 20 | 2. 参与者的自我介绍 21 | 3. 演示 xiaoneai/ants 22 | 4. 分析 tp-micro 和 teleport 框架代码 23 | 5. 答疑 24 | 6. 确定线下分享形式(标准包和开源项目) 25 | 26 | [语音实录](http://oqos7hrvp.bkt.clouddn.com/voice/20180411_voice.m4a) 27 | 28 | [语音实录(文字版本 by 录音宝)](/reading/20180411/20180411_voice/) 29 | 30 | -------------------------------------------------------------------------------- /content/night/20-2018-11-15-go-test.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: 由 genpost (https://github.com/hidevopsio/genpost) 代码生成器生成 3 | title: 第 20 期 go test 及测试覆盖率 4 | date: 2018-11-15T11:19:26+08:00 5 | author: mai 6 | --- 7 | 8 | ## 观看视频 9 | 10 | {{< youtube id="qkFFIIaTgHM" >}} -------------------------------------------------------------------------------- /content/night/21-2018-11-28-errors-in-go.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: 由 genpost (https://github.com/hidevopsio/genpost) 代码生成器生成 3 | title: 第 21 期 Go errors 处理及 zap 源码分析 4 | date: 2018-11-28T11:13:59+08:00 5 | author: 叶飞/阙坦 6 | --- 7 | 8 | ## 观看视频 9 | 10 | {{< youtube id="ImJim15N_Wc" >}} -------------------------------------------------------------------------------- /content/night/22-2018-12-06-go-ide-discuss.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: VSCode Goland Sublime Text 3 Vim 3 | title: 第 22 期 Go 开发工具讨论 4 | date: 2018-12-06T20:30:00+08:00 5 | author: 杨文/John/... 6 | --- 7 | 8 | ## 观看视频 9 | 10 | {{< youtube id="XjAQRnJj6zI" >}} -------------------------------------------------------------------------------- /content/night/23-2018-12-13-drone-guide.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Drone 简单介绍和部分源码分析 3 | title: 第 23 期 Drone 简单介绍和部分源码分析 4 | date: 2018-12-13T20:35:00+08:00 5 | author: 杨文 6 | --- 7 | 8 | ## 观看视频 9 | 10 | {{< youtube id="Vg5EvcStD4k" >}} 11 | 12 | ## 参考资料 13 | 14 | 1. [基于 gogs/gitlab 和 drone 搭建的 CI/CD 平台](https://maiyang.me/post/2018-08-11-gitlab-gogs-drone-cicd/) 15 | 2. [Drone 源码分析之同步 repos 的策略研讨](https://maiyang.me/post/2018-08-28-sync-repo-in-drone/) 16 | 3. [Drone 源码分析之数据库初始化](https://maiyang.me/post/2018-09-04-database-in-drone/) 17 | -------------------------------------------------------------------------------- /content/night/25-2018-12-27-tsdb.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: TSDB 引擎介绍,对比及存储细节 3 | title: 第 25 期 TSDB 引擎介绍,对比及存储细节 4 | date: 2018-12-27T20:35:00+08:00 5 | author: yuyang 6 | --- 7 | 8 | ## TSDB 引擎介绍,对比及存储细节 9 | 10 | 1. OpenTSDB 11 | 2. InfluxDB 12 | 3. Druid 13 | 14 | ## 观看视频 15 | 16 | {{< youtube id="W-8PiciSWRM" >}} 17 | -------------------------------------------------------------------------------- /content/night/26-2019-01-03-blog-with-github-netlify.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: 手把手教你基于 Github+Netlify 构建自动化持续集成的技术团队博客 3 | title: 第 26 期 Go 夜读之手把手教你基于 Github+Netlify 构建自动化持续集成的技术团队博客 4 | date: 2019-01-03T21:15:00+08:00 5 | author: John 6 | --- 7 | 8 | ## Github 9 | 10 | ## Netlify 11 | 12 | ## 观看视频 13 | 14 | {{< youtube id="we6qrILQRjY" >}} 15 | -------------------------------------------------------------------------------- /content/night/28-2019-01-17-go-mod-part-3.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: go mod 源码阅读 part 3 3 | title: 第 28 期 Go 夜读之 go mod 源码阅读 part 3 4 | date: 2019-01-17T20:05:00+08:00 5 | author: mai 6 | --- 7 | 8 | *Go 标准包阅读* 9 | 10 | Go 版本:go 1.11.5 11 | 12 | ## 学到的内容 13 | 14 | 1. `json:",omitempty"` 15 | 2. 16 | 17 | 方法一: 18 | ```golang 19 | if path[len(path)-1] == '/' { 20 | return fmt.Errorf("trailing slash") 21 | } 22 | ``` 23 | 24 | 方法二: 25 | 26 | ```golang 27 | strings.HasSuffix(path, "/") 28 | ``` 29 | 30 | benchmark 31 | 32 | 3. 33 | 34 | 方法一: 35 | ```golang 36 | strings.TrimSuffix(pathMajor, "-unstable") 37 | ``` 38 | 39 | 方法二: 40 | ```golang 41 | i := len(path) 42 | 43 | if strings.HasSuffix(path, "-unstable") { 44 | i -= len("-unstable") 45 | } 46 | ``` 47 | 48 | benchmark 49 | 50 | 4. 51 | 52 | ```golang 53 | if i := strings.Index(arg, "@"); i >= 0 { 54 | path, vers = arg[:i], arg[i+1:] 55 | } 56 | ``` 57 | 58 | 也可以用 `split(arg, "@")` 来实现。 59 | 60 | 61 | ## 观看视频 62 | 63 | {{< youtube id="tD7Aj6tKhGc" >}} 64 | -------------------------------------------------------------------------------- /content/night/30-2019-02-16-go-mod-part-4.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 go mod 源码阅读 part 4 3 | title: 第 30 期 Go 夜读之 go mod 源码阅读 part 4 4 | date: 2019-02-16T21:00:00+08:00 5 | author: mai 6 | --- 7 | 8 | *Go 标准包阅读* 9 | 10 | Go 版本:go 1.11.5 11 | 12 | ### net/http 13 | 14 | 1. \`\` 换行 15 | 16 | 本期没有视频回放。 17 | 18 | ## 观看视频 19 | 20 | {{< youtube id="" >}} 21 | -------------------------------------------------------------------------------- /content/night/31-2019-02-23-flag.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 flag 包源码阅读 3 | title: 第 31 期 Go 夜读之 flag 包源码阅读 4 | date: 2019-02-23T21:00:00+08:00 5 | author: mai 6 | --- 7 | 8 | *Go 标准包阅读* 9 | 10 | Go 版本:go 1.11.5 11 | 12 | ### 总结 13 | 14 | 1. \*v.URL = \*u 15 | 2. flag 下有 `package flag_test`?? 16 | 3. init 中定义相同的 stringvar ; 17 | 当一个文件中出现多个 init 函数时,他们都会被加载,并且以 init 出现在文件中的前后顺序执行。 18 | 4. 19 | 20 | ```golang 21 | type Value interface { 22 | String() string 23 | Set(string) error 24 | } 25 | type Getter interface { 26 | Value 27 | Get() interface{} 28 | } 29 | type boolFlag interface { 30 | Value 31 | IsBoolFlag() bool 32 | } 33 | ``` 34 | 35 | 5. `strconv.ParseBool` 的返回值可以被利用 36 | 37 | ```golang 38 | v, err := strconv.ParseBool(s) 39 | *b = boolValue(v) 40 | return err 41 | ``` 42 | 43 | ## 参考资料 44 | 45 | 1. [Go 语言中值 receiver 和指针 receiver 的对比(收集的一些资料)](https://maiyang.me/post/2018-12-12-values-receiver-vs-pointer-receiver-in-golang/) 46 | 47 | ## 观看视频 48 | 49 | {{< youtube id="z-9WEuUWqu4" >}} 50 | -------------------------------------------------------------------------------- /content/night/32-2019-03-02-etcd-raft.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 etcd raft 源码阅读 3 | title: 第 32 期 Go 夜读之 etcd raft 源码阅读 4 | date: 2019-03-02T21:05:00+08:00 5 | author: 缪昌新 6 | --- 7 | 8 | *etcd raft 阅读* 9 | 10 | etcd 版本:3.3.10 11 | 12 | 2019.3.2 晚上 13 | 14 | ### 总结 15 | 16 | etcd里的raft模块只实现了raft共识算法,而像消息的网络传输,数据存储都由上层应用来完成。 17 | 18 | 下面是各个文件(夹)的功能简介: 19 | 20 | * raftpb 21 | 22 | 用[Protocol Buffer](https://developers.google.com/protocol-buffers/)定义了一些需要序列化的数据结构,比如`Entry`和`Message`。 23 | 24 | * log_unstable.go 25 | 26 | `unstable`数据结构表示用于还没有被用户层持久化的数据,它维护了两部分内容`snapshot`和`entries`。 27 | 28 | * storage.go 29 | 30 | 这个文件定义了一个`Storage`接口,应用层需要实现这个接口,以提供存储和查询日志的能力。 31 | 32 | * log.go 33 | 34 | 维护本地日志信息。其中的`committed`和`applied`分别表示已提交和已经应用到状态机的日志索引。 35 | 36 | * progress.go 37 | 38 | Leader节点通过`Progress`这个数据结构来追踪一个follower的状态,并根据`Progress`里的信息来决定每次同步的日志项。 39 | 40 | * raft.go 41 | 42 | Raft协议的具体实现就在这个文件里。其中最重要的就是`Step`函数,它用来处理不同的消息。所以以后当我们想知道raft对某种消息的处理逻辑时,到这里找就对了。 43 | 44 | * node.go 45 | 46 | `node`的主要作用是应用层和共识模块(raft)的衔接。将应用层的消息传递给底层共识模块,并将底层共识模块共识后的结果反馈给应用层。 47 | 48 | ## 参考资料 49 | 50 | 1. [深入浅出 Raft - 基本概念](https://www.jianshu.com/p/138b4d267084) 51 | 2. [深入浅出 Raft - Membership Change](https://www.jianshu.com/p/99562bfec5c2) 52 | 3. [深入浅出 Raft - Leader 选举](https://www.jianshu.com/p/2b60542640e2) 53 | 4. [深入浅出 Raft - Optimization](https://www.jianshu.com/p/1bbd7162727d) 54 | 5. [Raft在etcd中的实现](http://blog.betacat.io/post/raft-implementation-in-etcd/) 55 | 6. [etcd contrib](https://github.com/etcd-io/etcd/tree/master/contrib) 56 | 7. [Etcd超全解:原理阐释及部署设置的最佳实践](https://mp.weixin.qq.com/s/kcWCxk0NbTuob0y6gN5emw) 57 | 58 | ## 观看视频 59 | 60 | {{< youtube id="sL02PsR20gE" >}} 61 | -------------------------------------------------------------------------------- /content/night/33-2019-03-07-defer-in-go.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 Go defer 和逃逸分析 3 | title: 第 33 期 Go 夜读之 Go defer 和逃逸分析 4 | date: 2019-03-07T21:05:00+08:00 5 | author: 饶全成 6 | --- 7 | 8 | 2019.3.7 晚上 9 | 10 | 11 | ## 观看视频 12 | 13 | {{< youtube id="-FtBBx44E3g" >}} 14 | -------------------------------------------------------------------------------- /content/night/35-2019-03-21-reading-context.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 context 源码阅读 3 | title: 第 35 期 context 源码阅读 4 | date: 2019-03-21T21:05:00+08:00 5 | author: mai 6 | --- 7 | 8 | ## 预习材料 9 | 10 | [第 35 期 Go 夜读之『context 包源码阅读』预习资料 #191](https://github.com/talkgo/night/issues/191) 11 | 12 | ## 观看视频 13 | 14 | {{< youtube id="LhEiCTkF2S8" >}} 15 | -------------------------------------------------------------------------------- /content/night/36-2019-03-28-reading-k8s-context.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 k8s context 实践源码阅读 3 | title: 第 36 期 k8s context 实践源码阅读 4 | date: 2019-03-28T21:05:00+08:00 5 | author: mai 6 | --- 7 | 8 | ## 实践 9 | 10 | 1. WithValue 11 | 2. WithCancel 12 | 3. WithTimeout 13 | 14 | `WithDeadline` 基本上没有用到。 15 | 16 | ## 参考资料 17 | 18 | 1. [How to correctly use context.Context in Go 1.7](https://medium.com/@cep21/how-to-correctly-use-context-context-in-go-1-7-8f2c0fafdf39) 19 | 2. [How to correctly use package context](https://youtu.be/-_B5uQ4UGi0) 20 | 3. [视频笔记:如何正确使用 Context - Jack Lindamood](https://blog.lab99.org/post/golang-2017-10-27-video-how-to-correctly-use-package-context.html) 21 | 22 | ## 观看视频 23 | 24 | {{< youtube id="JLuBPEeS9G8" >}} 25 | -------------------------------------------------------------------------------- /content/night/37-2019-04-01-talk-from-serverless-in-apache-pulsar.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 从 serverless 的一个设计说起 3 | title: 第 37 期 从 serverless 的一个设计说起 4 | date: 2019-04-01T21:05:00+08:00 5 | author: 冉小龙 6 | --- 7 | 8 | ## 参考资料 9 | 10 | 1. [预习材料](https://github.com/talkgo/night/issues/324) 11 | 2. [pulsar-effectively-once](https://streaml.io/blog/pulsar-effectively-once) 12 | 13 | ## 观看视频 14 | 15 | {{< youtube id="wfTQlM8eics" >}} 16 | -------------------------------------------------------------------------------- /content/night/38-2019-04-13-k8s-scheduler-reading.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 kubernetes scheduler 源码阅读 3 | title: 第 38 期 kubernetes scheduler 源码阅读 4 | date: 2019-04-13T21:05:00+08:00 5 | author: John 6 | --- 7 | 8 | ## 观看视频 9 | 10 | {{< youtube id="T83rJuIs7PE" >}} 11 | -------------------------------------------------------------------------------- /content/night/39-2019-04-18-init-function-in-go.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 init function 使用分析 3 | title: 第 39 期 init function 使用分析 4 | date: 2019-04-18T21:05:00+08:00 5 | author: mai 6 | --- 7 | 8 | ## 观看视频 9 | 10 | {{< youtube id="62mci2mPQDU" >}} 11 | -------------------------------------------------------------------------------- /content/night/4-2018-04-25-strings-part2.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第 4 期 2018-04-25 线下活动 3 | date: 2018-04-25T11:49:10+08:00 4 | --- 5 | >参与人数: 15 人 6 | 7 | *Go 标准包阅读* 8 | 9 | Go 版本:go 1.10.1 10 | 11 | ### strings 12 | 13 | - replace.go 14 | - replace_test.go 15 | - search.go 16 | - search_test.go 17 | 18 | ### 问题清单 19 | 20 | 以下是我们在阅读过程中的一些问题,希望可以引起大家的关注,也欢迎大家提出自己的理解,最好可以给以文章总结。 21 | 22 | 1. Boyer-Moore 算法 23 | 24 | ## 延伸阅读 25 | 26 | 0. [Boyer-Moore_string_search_algorithmde](http://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm) 27 | 1. [Boyer-Moore字符串搜索算法](https://zh.wikipedia.org/zh-hans/Boyer-Moore字符串搜索算法) 28 | 2. [字符串匹配的Boyer-Moore算法](http://www.ruanyifeng.com/blog/2013/05/boyer-moore_string_search_algorithm.html) 29 | 3. [grep之字符串搜索算法Boyer-Moore由浅入深(比KMP快3-5倍)](http://www.cnblogs.com/lanxuezaipiao/p/3452579.html) 30 | -------------------------------------------------------------------------------- /content/night/40-2019-04-27-atomic-value-in-go.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 atomic.Value 的使用和源码分析 3 | title: 第 40 期 atomic.Value 的使用和源码分析 4 | date: 2019-04-27T21:05:00+08:00 5 | author: mai 6 | --- 7 | 8 | ## 观看视频 9 | 10 | {{< youtube id="pyics4WyUmA" >}} 11 | -------------------------------------------------------------------------------- /content/night/41-2019-05-12-golint-golangci-lint.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 golint 及 golangci-lint 的介绍和使用 3 | title: 第 41 期 golint 及 golangci-lint 的介绍和使用 4 | date: 2019-05-12T20:00:00+08:00 5 | author: mai 6 | --- 7 | 8 | ## 观看视频 9 | 10 | {{< youtube id="z42y4tpRmbw" >}} 11 | -------------------------------------------------------------------------------- /content/night/42-2019-05-16-go-failpoint-design.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 An Introduction to Failpoint Design 3 | title: 第 42 期 An Introduction to Failpoint Design 4 | date: 2019-05-16T21:00:00+08:00 5 | author: 龙恒 6 | --- 7 | 8 | ## 观看视频 9 | 10 | {{< youtube id="ke7zzny9dxU" >}} 11 | -------------------------------------------------------------------------------- /content/night/43-2019-05-23-gomonkey-framework-design-and-practives.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 gomonkey 框架设计与应用实践 3 | title: 第 43 期 gomonkey 框架设计与应用实践 4 | date: 2019-05-23T21:30:00+08:00 5 | author: 张晓龙 6 | --- 7 | 8 | ## 观看视频 9 | 10 | {{< youtube id="OpuX47E7B2w" >}} 11 | -------------------------------------------------------------------------------- /content/night/44-2019-05-29-go-map-reading.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 Go map 源码阅读分析(20190529第44期) 3 | title: 第 44 期 Go map 源码阅读分析 4 | date: 2019-05-29T21:10:00+08:00 5 | author: 饶全成 6 | --- 7 | 8 | ## 观看视频 9 | 10 | {{< youtube id="P2v3kvztWU0" >}} 11 | -------------------------------------------------------------------------------- /content/night/45-2019-05-30-goim-reading.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 goim 架构设计与源码分析(20190530第45期) 3 | title: 第 45 期 goim 架构设计与源码分析 4 | date: 2019-05-30T21:10:00+08:00 5 | author: tsingson 6 | --- 7 | 8 | ## 观看视频 9 | 10 | {{< youtube id="bFniRH3ifx8" >}} 11 | -------------------------------------------------------------------------------- /content/night/47-2019-06-12-tidb-exector-reading.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读 && TiDB 源码阅读之 Executor 3 | title: 第 47 期 TiDB 源码阅读之 Executor 4 | date: 2019-06-12T21:10:00+08:00 5 | author: chenshuang 6 | --- 7 | 8 | ## TiDB Executor 内容介绍 9 | 10 | 本次分享主要讲 TiDB 中 insert/update/delete/select, 以及 DDL 等是如何执行的,以及涉及到相关模块。大概会涉及以下模块: 11 | 12 | * executor 13 | * distsql 14 | * ddl 15 | 16 |  17 | 18 | PPT: [TiDB Executor 源码阅读.pdf](https://github.com/talkgo/night/files/3281080/TiDB.Executor.pdf) 19 | 20 | ## 推荐阅读 21 | 22 | * [Select 语句概览](https://pingcap.com/blog-cn/tidb-source-code-reading-6/) 23 | * [INSERT 语句详解](https://pingcap.com/blog-cn/tidb-source-code-reading-16/) 24 | * [DDL 源码解析](https://pingcap.com/blog-cn/tidb-source-code-reading-17/) 25 | 26 | ## 视频回看 27 | 28 | 1. [TiDB 源码学习之 Executor - YouTube](https://youtu.be/Rcrm4w7sqbM) 29 | 2. [TiDB 源码学习之 Executor - Bilibili](https://www.bilibili.com/video/av55403428/) 30 | 31 | PPT: https://github.com/talkgo/night/files/3281080/TiDB.Executor.pdf 32 | 33 | ## 问题 34 | 35 | - 表的信息是怎么存的呢 36 | - id的生成规则是什么 37 | - 如果索引里面不保存handle_id,那怎么根据索引找到这行数据呢 38 | - 索引字段很大会不会有问题,作为id的一部分的话 39 | - 单条6m的限制是怎么计算出来的?还是压力测出来的? 40 | - ddl时,job放到tikv的队列,tikv是分布式的,job具体是放到哪个tikv上的呢? 41 | - 并行ddl 如何跑 42 | - tikv整体上可以看成一个kv store 43 | - region这部分概念可以配合hbase去看看能更好的理解 44 | - 难道own tidb server要遍历所有的tikv server上的queue,去取ddl的job? 45 | - tidb 的统计信息也是放一个表里面,每次parse 都会去拿这个信息,这样的话请求到一个region,这个表是不是很容易成为热点 46 | 47 | ## 观看视频 48 | 49 | {{< youtube id="Rcrm4w7sqbM" >}} 50 | -------------------------------------------------------------------------------- /content/night/51-2019-07-18-sync-errgroup.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 sync/errgroup 源码阅读 3 | title: 第 51 期 Go 夜读之 sync/errgroup 源码阅读 4 | date: 2019-07-18T21:10:00+08:00 5 | author: mai 6 | --- 7 | 8 | ## golang.org/x/sync/errgroup 9 | 10 | errgroup 唯一的坑是for循环里千万别忘了 i, x := i, x,以前用 waitgroup 的时候都是 go func 手动给闭包传参解决这个问题的,errgroup 的.Go没法这么干,犯了好几次错才改过来" 11 | 12 | ## 观看视频 13 | 14 | {{< youtube id="CQOZtzmgLvw" >}} 15 | -------------------------------------------------------------------------------- /content/night/52-2019-07-25-httprouter-guide.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 httprouter 简介 3 | title: 第 52 期 Go 夜读之 httprouter 简介 4 | date: 2019-07-25T21:10:00+08:00 5 | author: 曹大 6 | --- 7 | 8 | ## httprouter 简介 9 | 10 | 详细内容,可以查看 https://cch123.github.io/httprouter/ 11 | 12 | ## 观看视频 13 | 14 | {{< youtube id="BLYX6SKxFJA" >}} 15 | -------------------------------------------------------------------------------- /content/night/53-2019-08-01-build-in-delete-from-map-in-go.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 build in func delete from map 3 | title: 第 53 期 Go 夜读之 build in func delete from map 4 | date: 2019-08-01T21:10:00+08:00 5 | author: mai 6 | --- 7 | 8 | ## Go 夜读第 53 期 delete from map in go 9 | 10 | 突然有一个需求要删除 map 中的一些过滤数据。 11 | >由此查阅了一些资料,然后促成此次分享。 12 | 13 | PPT: 14 | [build-in func delete from map in go.pptx](https://github.com/talkgo/night/files/3453966/build-in.func.delete.from.map.in.go.pptx) 15 | 16 | ## 分享时间 17 | 18 | 2019-08-01 21:00:00 19 | 20 | ## 分享平台 21 | 22 | [zoom 在线直播 - https://zoom.us/j/6923842137](https://zoom.us/j/6923842137) 23 | 24 | ## 参考资料 25 | 26 | - https://stackoverflow.com/questions/1736014/delete-mapkey-in-go 27 | - https://blog.cyeam.com/json/2017/11/02/go-map-delete 28 | - https://blog.golang.org/go-maps-in-action 29 | - https://gobyexample.com/maps 30 | - https://stackoverflow.com/questions/23229975/is-it-safe-to-remove-selected-keys-from-map-within-a-range-loop 31 | - https://www.cnblogs.com/qcrao-2018/p/10903807.html 32 | - https://appdividend.com/2019/05/12/golang-maps-tutorial-with-examples-maps-in-go-explained/ 33 | - https://www.jianshu.com/p/92e9efec8688 34 | - https://www.reddit.com/r/golang/comments/5tfx7i/why_delete_doesnt_return_a_bool/ 35 | - https://www.liwenzhou.com/posts/Go/08_map/ 36 | - https://github.com/EDDYCJY/blog/tree/master/map 37 | 38 | ## 观看视频 39 | 40 | {{< youtube id="sn810EcpOVs" >}} 41 | -------------------------------------------------------------------------------- /content/night/54-2019-08-14-tidb-sql-tools.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 TiDB SQL 兼容性测试工具简介 3 | title: 第 54 期 Go 夜读之 TiDB SQL 兼容性测试工具简介 4 | date: 2019-08-14T21:00:00+08:00 5 | author: PingCAP 6 | --- 7 | 8 | ## Go 夜读第 54 期 TiDB SQL 兼容性测试工具简介 9 | 10 | 本次分享包含两方面内容: 11 | 12 | 通过 MySQL yacc 文件生成 SQL Cases,并用于 TiDB 的兼容性测试的原理讲解。 13 | TiDB Parser 兼容性社区活动介绍,手把手的演示如何参与本次社区活动。 14 | 15 | (彩蛋:Parser Working Group 成立了,有兴趣的小伙伴可以看视频然后扫描加入。) 16 | 17 | ## 分享时间 18 | 19 | 2019-08-14 21:00:00 20 | 21 | ## 分享平台 22 | 23 | [zoom 在线直播 - https://zoom.us/j/6923842137](https://zoom.us/j/6923842137) 24 | 25 | ## 参考资料 26 | 27 | - [三十分钟成为 Contributor | 提升 TiDB Parser 对 MySQL 8.0 语法的兼容性](https://pingcap.com/blog-cn/30mins-become-contributor-of-tidb-20190808/) 28 | 29 | ## 观看视频 30 | 31 | {{< youtube id="Hmu3F1Vafqc" >}} 32 | -------------------------------------------------------------------------------- /content/night/57-2019-08-29-sync-semaphore.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 sync/semaphore 源码浅析 3 | title: 第 57 期 sync/semaphore 源码浅析 4 | date: 2019-08-29T21:00:00+08:00 5 | author: Felix 6 | --- 7 | 8 | ## Go 夜读第 57 期 sync/semaphore 源码浅析 9 | 10 | 内容简介 11 | 12 | 主要分析 golang.org/x/sync/semaphore 相关代码和 semaphore 部分使用场景。 13 | 14 | 内容大纲 15 | - semaphore 定义 16 | - 源码分析 17 | - Q&A 18 | 19 | ## 分享地址 20 | 21 | 2019.08.29, 21:00 ~ 21:40, UTC+8 22 | 23 | https://zoom.us/j/6923842137 24 | 25 | ## 进一步阅读的材料 26 | 27 | - [semaphore 定义](https://en.wikipedia.org/wiki/Semaphore_(programming)) 28 | - [源码](https://github.com/golang/sync/blob/master/semaphore/semaphore.go) 29 | - [分享 PPT](https://docs.google.com/presentation/d/17Moou4_Z5kD9xuvCIFUT4d7KbkyS73DCQmdOPlJ5P2U/edit?usp=sharing) 30 | 31 | ## 补充资料 32 | - [同步原语](https://draveness.me/golang/concurrency/golang-sync-primitives.html) 33 | - [结合 errgroup 使用](https://github.com/golang/go/issues/27837#issuecomment-513443404) 34 | - [关于是否应该支持 resize 的讨论](https://github.com/golang/go/issues/29721) 35 | - [semaphore 实现的 taskpool](https://github.com/eleniums/async/blob/master/pool.go) 36 | 37 | 更多见:https://github.com/talkgo/night/issues/456 38 | 39 | 40 | --- 41 | 42 | 43 | ## 观看视频 44 | 45 | {{< youtube id="VEtdLBFY_y4" >}} 46 | -------------------------------------------------------------------------------- /content/night/58-2019-09-05-whats-new-in-go1.13.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 What's new in Go 1.13? 3 | title: 第 58 期 What's new in Go 1.13? 4 | date: 2019-09-05T21:05:00+08:00 5 | author: Go 夜读 SIG 小组 6 | --- 7 | 8 | ## Go 夜读第 58 期 What's new in Go 1.13? 9 | 10 | 内容简介 11 | 12 | 主要介绍了刚刚发布的 Go 1.13 Release 的内容。 13 | 14 | 内容大纲 15 | - Go modules 16 | - Toolchain 17 | - Runtime 18 | - CoreLibrary Improve Performance 19 | - Q&A 20 | 21 | ## 分享地址 22 | 23 | 2019-09-05, 21:00 ~ 22:10, UTC+8 24 | 25 | https://zoom.us/j/6923842137 26 | 27 | ## 进一步阅读的材料 28 | 29 | - [https://golang.org/doc/go1.13](https://golang.org/doc/go1.13) 30 | - [improve defer perfermance 30%](https://github.com/golang/go/commit/fff4f599fe1c21e411a99de5c9b3777d06ce0ce6) 31 | - [goproxy.cn - 为中国 Go 语言开发者量身打造的模块代理](https://mp.weixin.qq.com/s/Pw_a5heUgyIkuJrXF4HCVg) 32 | 33 | 更多见:https://github.com/talkgo/night/issues/465 34 | 35 | --- 36 | 37 | 38 | ## 观看视频 39 | 40 | {{< youtube id="jVUy47OrpRk" >}} 41 | -------------------------------------------------------------------------------- /content/night/6-2018-05-17-strings-part4.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第 6 期 2018-05-17 线下活动 - Go 标准包阅读 3 | date: 2018-05-17T11:49:10+08:00 4 | --- 5 | >参与人数: 12 人 6 | 7 | *Go 标准包阅读* 8 | 9 | Go 版本:go 1.10.1 10 | 11 | ### strings 12 | 13 | - strings.go 14 | 15 | ### 问题清单 16 | 17 | 以下是我们在阅读过程中的一些问题,希望可以引起大家的关注,也欢迎大家提出自己的理解,最好可以给以文章总结。 18 | 19 | 0. // Remove if golang.org/issue/6714 is fixed 20 | 1. bp := copy(b, a[0]) 21 | 2. return len(s) >= len(prefix) && s[0:len(prefix)] == prefix 各种开发语言都有的短路机制;字符串底层也是可以用作切片的; 22 | 3. 为什么要判断这个错误: if c == utf8.RuneError 23 | 4. c -= 'a' - 'A' (小写转大写的算法) 24 | 5. // Since we cannot return an error on overflow, 25 | // we should panic if the repeat will generate 26 | // an overflow. 27 | // See Issue golang.org/issue/16237 28 | 6. truth 29 | 7. asciiSet (bitset 标记位,存在标记为1) 30 | 31 | 传一个字符串,把字符串包含的ascii,对应的256位,进行映射。 32 | 33 | 8. Unicode 包很多都看不懂。 34 | 35 | 9. func isSeparator(r rune) bool 36 | 37 | ## 延伸阅读 38 | 39 | 1. -------------------------------------------------------------------------------- /content/night/66-2019-11-07-paper-reading-csp.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 Paper Reading CSP 理解顺序进程间通信 3 | title: 第 66 期 Paper Reading CSP 理解顺序进程间通信 4 | date: 2019-11-07T21:00:00+08:00 5 | author: 欧长坤@慕尼黑大学 6 | --- 7 | 8 | ## Go 夜读第 66 期 Paper Reading CSP 理解顺序进程间通信 9 | 10 | 本期 Go 夜读是由 Go 夜读 SIG 核心小组成员欧长坤给大家带来的经典论文 CSP 的 Paper Reading。 11 | 12 | ## CSP 是什么? 13 | 14 | 我们常常在讨论中提及 CSP,但鲜有人能真正说清楚 CSP 的演进历史,及其最核心的基本思想。我们已经对 Go 提供的并发原语足够熟悉了,是时候深入理解其背后的基础理论 —— 顺序进程间通信(Communicating Sequential Processes, CSP)了。本次分享我们针对 [Hoare 1978] 探讨 CSP 理论的原始设计(CSP 1978),主要围绕以下几个问题展开: 15 | 16 | Tony Hoare 提出 CSP 的时代背景是什么? 17 | - CSP 1978 理论到底有哪些值得我们研究的地方? 18 | - CSP 1978 理论是否真的就是我们目前熟知的基于通道的同步方式? 19 | - CSP 1978 理论的早期设计存在什么样的缺陷? 20 | 21 | ## 大纲 22 | 23 | - CSP 1978 的诞生背景 24 | - CSP 1978 的主要内容及其结论 25 | - CSP 1978 理论中存在的设计缺陷 26 | - 讨论与反思 27 | 28 | ### 分享 Slides 29 | 30 | - https://docs.google.com/presentation/d/1N5skL6vR9Wxk-I82AYs3dlsOsJkUAGJCsb5NGpXWpqo/edit?usp=sharing 31 | 32 | ## 回看视频 33 | 34 | - https://www.bilibili.com/video/av74891823/ 35 | - https://youtu.be/Z8ZpWVuEx8c 36 | 37 | ## 参考资料 38 | 39 | - [Hoare 1978] [Hoare, C. A. R. (1978). Communicating sequential processes. Communications of the ACM, 21(8), 666–677.](https://spinroot.com/courses/summer/Papers/hoare_1978.pdf) 40 | - [Ou 2019a] [CSP1978 的 Go 语言实现](https://github.com/changkun/gobase/blob/master/csp/csp.go) 41 | - [Ou 2019b] [第 56 期 channel & select 源码分析](https://github.com/talkgo/night/issues/450) 42 | - [Ou 2019c] [第 59 期 Real-world Go Concurrency Bugs](https://github.com/talkgo/night/issues/464) 43 | 44 | 45 | --- 46 | 47 | ## 观看视频 48 | 49 | {{< youtube id="Z8ZpWVuEx8c" >}} 50 | -------------------------------------------------------------------------------- /content/night/67-2019-11-14-sql-pool-reading.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 Go database/sql 数据库连接池分析 3 | title: 第 67 期 Go database/sql 数据库连接池分析 4 | date: 2019-11-14T21:00:00+08:00 5 | author: 邹文通@POP 6 | --- 7 | 8 | ## Go 夜读第 67 期 Go database/sql 数据库连接池分析 9 | 10 | 本期 Go 夜读是由 POP 后端团队的邹文通给大家带来的 Go 标准包 database/sql 数据库连接池源码剖析。 11 | 12 | ### 大纲 13 | 14 | - sql 连接池简介 15 | - 连接池的工作原理 16 | - sql 包连接池源码分析 17 | - 连接池使用 tips 18 | 19 | ## Slides 20 | 21 | - https://docs.google.com/presentation/d/10kGjeHGbB0h0Cz8f58reXOyCdyWSOSKrr2160IFNla4/edit?usp=sharing 22 | 23 | ## 回看视频 24 | 25 | - https://www.bilibili.com/video/av75690189/ 26 | - https://youtu.be/JKJ8ehtiqUM 27 | 28 | ---- 29 | 30 | ## QA 31 | 32 | ### 1. database/sql 中 MaxIdleConns 和 MaxOpenConns 应该怎么设置才是相对合理的,在选择设置具体的值时,他们又受什么因素影响呢? 33 | 34 | - 关于这个问题,可以参考这篇文章 [Production-ready Database Connection Pooling in Go](https://making.pusher.com/production-ready-connection-pooling-in-go/). 文章的建议是 MaxOpenConns 应该和实际的打开的连接数的监测值相关。然后按照 MaxOpenConns 的一定比值设置 MaxIdleConns,比方说 50%,这个值取决于你对业务的预估。每维持一个闲散连接,会造成 1MB 左右的客户端内存开销和 2MB 左右的数据库内存开销,CPU 开销相对小一点。文章还给出了一些 benchmark 的测试,在默认 MaxIdleConns 和 MaxIdleConns = 50% * MaxOpenConns 情况下的一个性能的对比,可以参考一下。 35 | 36 | ## 参考资料 37 | 38 | - [Go组件学习——database/sql数据库连接池你用对了吗](https://juejin.im/post/5d624abde51d45621655352c) 39 | - [Go组件学习——手写连接池并没有那么简单](https://mp.weixin.qq.com/s/-2T9BovG8TG32DQKn93LaA) 40 | - [Chapter 8 Connection Pooling with Connector/J](https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-usagenotes-j2ee-concepts-connection-pooling.html) 41 | - [彻底弄懂mysql(二)--连接方式](https://blog.csdn.net/LYue123/article/details/89285157) 42 | 43 | 44 | --- 45 | 46 | ## 观看视频 47 | 48 | {{< youtube id="JKJ8ehtiqUM" >}} 49 | -------------------------------------------------------------------------------- /content/night/69-2019-11-28-devops.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之基于 Go 语言周边生态打造的行业技术中台 3 | title: 第 69 期 DevOps 实践之路 - 基于 Go 语言周边生态打造的行业技术中台 4 | date: 2019-11-28T21:00:00+08:00 5 | author: 杨晖@腾讯教育 6 | --- 7 | 8 | ## Go 夜读第 69 期基于 Go 语言周边生态打造的行业技术中台 9 | 10 | 本期 Go 夜读是由杨晖给大家带来的『基于 Go 语言周边生态打造的行业技术中台』。 11 | 12 | ### 作者介绍 13 | 14 | 杨晖,腾讯云,教育行业技术负责人,打造教育行业技术解决方案,提供统一的对外技术中台服务。 15 | 16 | ### 大纲 17 | 18 | Go 语言生态在腾讯云教育行业中的运用和实践 19 | 20 | 1. 腾讯教育介绍 21 | 2. 建设思路 22 | 3. 详细设计 23 | 4. 实践 24 | 5. 总结 & 后续优化 25 | 26 | ## 回看视频 27 | 28 | - https://www.bilibili.com/video/av77363419 29 | - https://youtu.be/wS897lDB_Lk 30 | 31 | ## 分享内容 PPT 32 | 33 | https://github.com/talkgo/night/issues/487 34 | 35 | --- 36 | 37 | ## 观看视频 38 | 39 | {{< youtube id="wS897lDB_Lk" >}} 40 | -------------------------------------------------------------------------------- /content/night/70-2019-12-05-go-details.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 Go 中不常注意的各种细节集锦 3 | title: 第 70 期 Go 中不常注意的各种细节集锦 4 | date: 2019-12-05T21:00:00+08:00 5 | author: 老貘@Golang101作者 6 | --- 7 | 8 | ## Go 夜读第 70 期 Go 中不常注意的各种细节集锦 9 | 10 | 本期 Go 夜读是由老貘给大家带来的『Go 中不常注意的各种细节集锦』。 11 | 12 | ### 作者介绍 13 | 14 | 老貘,《Golang 101 语言》一书的作者。 15 | 16 | ### 背景 17 | 18 | Go 语言简单易上手,很多 Go 程序员用了几年 Go 之后,常会觉得对 Go 的各方面已经了如指掌。 19 | 但是我发现实践中大家常常对 Go 中的一些细节并不了解。虽然这并不妨碍使用 Go,但是知道这些细节会对大家更好更职业地使用 Go 带来帮助。 20 | 21 | ### 大纲 22 | 23 | - Go 中的断行规则导致的一些反直觉例子 24 | - Go 中一些和类型推断相关的细节。 25 | - 各种场景下的表达式估值顺序 26 | - might be more 27 | 28 | ## 回看视频 29 | 30 | - https://www.bilibili.com/video/av78186949 31 | - https://youtu.be/kcwHwN8nTP8 32 | 33 | ## 分享内容 PPT 34 | 35 | https://github.com/talkgo/night/issues/521 36 | 37 | --- 38 | 39 | ## 观看视频 40 | 41 | {{< youtube id="kcwHwN8nTP8" >}} 42 | -------------------------------------------------------------------------------- /content/night/71-2019-12-12-go-ini.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 go-ini 配置库评析 3 | title: 第 71 期 go-ini 配置库评析 4 | date: 2019-12-12T21:00:00+08:00 5 | author: 无闻 6 | --- 7 | 8 | ## 【Go 夜读】#71 go-ini 配置库评析 9 | 10 | go-ini 作为目前 Go 语言最流行的 INI 解析库,有哪些特点、有哪些不足,开发的初衷和未来。 11 | 12 | ## 大纲 13 | 14 | 1. 开发初衷 15 | 2. 与市面上其它库的比较 16 | 3. 有哪些特点和不足 17 | 4. 设计思路 18 | 5. 性能对比 19 | 6. 后续功能展望 20 | 21 | ## 分享者自我介绍 22 | 23 | 无闻,目前就职于初创企业 Sourcegraph,软件工程师,没什么特长,就是啥都要干一点。 24 | 25 | ## 分享时间 26 | 27 | 2019-12-12 21:00 UTC+8 28 | 29 | ## 分享地址 30 | 31 | https://zoom.us/j/6923842137 32 | 33 | ## Slides 34 | 35 | https://docs.google.com/presentation/d/1ruDCybd9v7oWBx3WoIC-G26PjfnOdu3GwfSphED8UlM/edit?usp=sharing 36 | 37 | ## 参考资料 38 | 39 | 官方文档:https://ini.unknwon.io/ 40 | 41 | --- 42 | 43 | ## 观看视频 44 | 45 | {{< youtube id="783MGw53gfw" >}} 46 | -------------------------------------------------------------------------------- /content/night/74-2020-01-02-time-in-go-1-14.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 time.Timer 源码分析 (Go 1.14) 3 | title: 第 74 期 time.Timer 源码分析 (Go 1.14) 4 | date: 2020-01-02T21:00:00+08:00 5 | author: 欧长坤 6 | --- 7 | 8 | ## 【Go 夜读】#74 time.Timer 源码分析 (Go 1.14) 9 | 10 | time 是一个很有意思的包,除去需要获取当前时间的 Now 这一平淡无奇、直接对系统调用进行封装( `runtime.nanotime` )的函数外,其中最有意思的莫过于它所提供的 Timer 和 Ticker 了。他们的实现,驱动了诸如 `time.After`, `time.AfterFunc`, `time.Tick`, `time.Sleep` 等方法。 11 | 12 | 即将发布的 Go 1.14 将为 Timer 及其相关依赖带来大幅性能,本次分享我们就来详细分析以下 Go 13 | 1.14 中 `time.Timer` 的源码及其演进过程。 14 | 15 | ## 大纲 16 | 17 | - 调度器与调度循环 18 | - Timer 状态机 19 | - Timer 的启动、终止与重置 20 | - Timer 的触发时机 21 | - Go 1.10 以前以及 Go 1.10 的 Timer 实现 22 | 23 | ## 分享时间 24 | 25 | 2020-01-02 21:00 UTC+8 26 | 27 | ## 分享地址 28 | 29 | https://zoom.us/j/6923842137 30 | 31 | ## Slides 32 | 33 | [Google Slides](https://docs.google.com/presentation/d/1c2mRWA-FiihgpbGsE4uducou7X5d4WoiiLVab-ewsT8/edit?usp=sharing) 34 | 35 | ## 参考资料 36 | 37 | - [runtime: improve timers scalability on multi-CPU systems](https://github.com/golang/go/commit/76f4fd8a5251b4f63ea14a3c1e2fe2e78eb74f81) 38 | - [runtime: make timers faster](https://github.com/golang/go/commit/6becb033341602f2df9d7c55cc23e64b925bbee2) 39 | - [Go 夜读第 56 期:channel & select 源码分析](https://github.com/talkgo/night/issues/450) 40 | - [Go 语言原本: 计时器](https://changkun.de/golang/zh-cn/part2runtime/ch06sched/timer/) 41 | - [timer-based task scheduler](https://github.com/changkun/sched) 42 | 43 | --- 44 | 45 | ## 观看视频 46 | 47 | {{< youtube id="XJx0eTP-y9I" >}} 48 | -------------------------------------------------------------------------------- /content/night/75-2020-02-06-the-state-of-go-in-2020.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 2020 年 Go 的一些发展计划(Go 1.14 && Go 1.15) 3 | title: 第 75 期 2020 年 Go 的一些发展计划(Go 1.14 && Go 1.15) 4 | date: 2020-02-06T21:00:00+08:00 5 | author: 杨文 6 | --- 7 | 8 | ## 【Go 夜读】#75 2020 年 Go 的一些发展计划 9 | 10 | 聊聊即将发布的 go 1.14 都有哪些新特性和性能提升,然后再跟大家一起看看 go 1.15 的 Proposal。 11 | 最后我和大家一起谈谈你对 pkg.go.dev 的看法。 12 | 13 | ## 大纲 14 | 15 | 1. go 1.14 介绍 16 | 2. go 1.15 17 | 3. pkg.go.dev 18 | 19 | ## 分享者自我介绍 20 | 21 | 杨文, POP 22 | 23 | ## 分享时间 24 | 25 | 2020-02-06 21:00:00 UTC+8 26 | 27 | ## 分享地址 28 | 29 | https://zoom.us/j/6923842137 30 | 31 | ## Slides 32 | 33 | https://docs.google.com/presentation/d/1cXXbr5i9P3JE9DjVDfnK9yxZWUwMxs-VWKgScXc3D80/edit?usp=sharing 34 | 35 | ## 参考资料 36 | 37 | - https://golang.org/doc/go1.14 38 | - https://blog.golang.org/pkg.go.dev-2020 39 | - https://blog.golang.org/go1.15-proposals 40 | - https://maiyang.me/post/2020-02-05-image-jpeg-decode-is-slow/ 41 | 42 | ---- 43 | 44 | ## 备注 45 | 46 | 针对此次分享的 QA 请分享者在分享之后,整理同步到此 issues 后面。 47 | 48 | 49 | --- 50 | 51 | ## 观看视频 52 | 53 | {{< youtube id="hAshoKXMMu0" >}} 54 | -------------------------------------------------------------------------------- /content/night/76-2020-02-20-kubernetes-scheduler-design.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 Kubernetes Scheduler 设计与实现 3 | title: 第 76 期 Kubernetes Scheduler 设计与实现 4 | date: 2020-02-20T21:00:00+08:00 5 | author: Draven 6 | --- 7 | 8 | ## 【Go 夜读】#76 Kubernetes Scheduler 设计与实现 9 | 10 | 谈谈 Kubernetes 的架构设计以及 Kubernetes Scheduler 怎么把你的 Pod 调度到某个 Node 上的。 11 | 12 | ## 大纲 13 | 14 | + Kubernetes 架构设计 15 | + Kubernetes 调度器历史与设计演变 16 | + 基于谓词与优先级的调度器 17 | + 基于调度框架的调度器 18 | + Kubernetes 调度器实现分析 19 | + 番外篇(Optional) 20 | + 反调度器 21 | + 批处理调度器 22 | 23 | ## 分享者自我介绍 24 | 25 | Draven,[面向信仰编程](https://draveness.me/) 作者,Kubernetes 搬砖工,~负责给 issue 贴 Label~。 26 | 27 | ## 分享时间 28 | 29 | 2020-02-20 21:00:00 UTC+8 (真是个好日子) 30 | 31 | ## Slides 32 | 33 | https://docs.google.com/presentation/d/1zVftY8VhOfTqGYvQogFMUvB8WLTCIPJXUmeZnDOGzNE/edit?usp=sharing 34 | 35 | ## 参考资料 36 | 37 | + [调度系统设计精要](https://draveness.me/system-design-scheduler) 38 | + [Go 语言调度器的实现原理](https://draveness.me/golang/docs/part3-runtime/ch06-concurrency/golang-goroutine/) 39 | + [谈 Kubernetes 的架构设计与实现原理](https://draveness.me/understanding-kubernetes) 40 | 41 | ---- 42 | 43 | ## 观看视频 44 | 45 | {{< youtube id="1cQt2bXJtME" >}} 46 | -------------------------------------------------------------------------------- /content/night/77-2020-03-05-reading-go-earnings.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之阅读 Go 源码带来的收益 3 | title: 第 77 期阅读 Go 源码带来的收益 4 | date: 2020-03-05T21:00:00+08:00 5 | author: 杨文 6 | --- 7 | 8 | ## 【Go 夜读】#77 阅读 Go 源码带来的收益 9 | 10 | 结合我最近阅读的 Go 源码,进而应用到开源项目,并反馈到我们项目的过程,来跟大家聊聊阅读 Go 源码带来的收益。 11 | 12 | ## 大纲 13 | 14 | - 了解 Go 代码的设计与实现(学习) 15 | - 了解 Go 的代码变更缘由(学习+知其所以然+应用实践) 16 | - 了解 Go 团队的工作模式(更高效) 17 | - 了解 Go 周边生态(丰富自己) 18 | 19 | ## 分享者自我介绍 20 | 21 | 杨文,POP,Go 夜读 SIG 小组成员 22 | 23 | ## 分享时间 24 | 25 | 2020-03-05 21:00:00 UTC+8 26 | 27 | ## Slides 28 | 29 | https://docs.google.com/presentation/d/1-OPi5xZRm-RSnpDrT-6SdGF6srccqejkhYJrxwf278Q/edit?usp=sharing 30 | 31 | ---- 32 | 33 | ## 观看视频 34 | 35 | {{< youtube id="cWSTLlE59rY" >}} 36 | -------------------------------------------------------------------------------- /content/night/78-2020-03-11-go-scheduler-reading.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 Go Schedular 源码阅读 3 | title: 第 78 期 Go Schedular 源码阅读 4 | date: 2020-03-11T21:00:00+08:00 5 | author: 饶全成 6 | --- 7 | 8 | ## 【Go 夜读】#78 Go Schedular 源码阅读 9 | 10 | 总体讲一下调度器,再快速过一遍代码。 11 | 12 | ## 大纲 13 | 14 | - 调度循环的建立 15 | - GPM 状态机 16 | - sysmon 线程做了什么? 17 | 18 | ## 分享者自我介绍 19 | 20 | 饶全成,Go 夜读 SIG 小组成员 21 | 22 | ## 分享时间 23 | 24 | 2020-03-11 21:00:00 UTC+8 25 | 26 | ## Slides 27 | 28 | https://qcrao.com/ishare/go-scheduler/ 29 | 30 | ## 参考资料 31 | 32 | - 【goroutine 调度器系列教程】http://mp.weixin.qq.com/mp/homepage?__biz=MzU1OTg5NDkzOA==&hid=1&sn=8fc2b63f53559bc0cee292ce629c4788&scene=18#wechat_redirect 33 | - 【码农桃花源】https://qcrao.com/2019/09/02/dive-into-go-scheduler/ 34 | - 【欧神】https://github.com/changkun/go-under-the-hood 35 | 36 | ---- 37 | 38 | ## 观看视频 39 | 40 | {{< youtube id="B-ozWjqnX24" >}} 41 | -------------------------------------------------------------------------------- /content/night/79-2020-03-12-go-micro-tools.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 Go-Micro 运行时工具集 3 | title: 第 79 期 Go-Micro 运行时工具集 4 | date: 2020-03-12T21:00:00+08:00 5 | author: 舒先 6 | --- 7 | 8 | ## 【Go 夜读】#79 Go-Micro 运行时工具集 9 | 10 | 介绍 Go-Micro 工具集的特性。 11 | 12 | ## 大纲 13 | 14 | - Micro API(Gateway) 15 | - Micro CLI(命令行工具) 16 | - Micro Proxy(Go-Micro服务代理) 17 | - 如果时间充裕:Micro 工具集的发展(Network,Run、Tunnel、Platform) 18 | 19 | ## 分享者自我介绍 20 | 21 | Micro 中国团队 22 | 23 | - [陈洪波](https://github.com/hb-chen):本期资料提供与审核,10年,成都云创新技术经理,Gopher、Phper,全栈码农,专注于微服务架构&服务网格技术的应用。 24 | - [Edward Chen](https://github.com/crazybber):本期资料提供与审核,10年+,Honeywell HBT 研发技术专家,擅长Racher/K8S/Go/C#/C++/C/Typescript,专注于大规模IOT容器化微服务架构,一线开发。 25 | - [舒先](https://github.com/printfcoder):本期资料提供与主讲,7年+金融级微服务开发经验,OPPO,Micro维护者团队成员,负责中国生态。 26 | - [徐旭](https://github.com/Allenxuxu):本期资料提供与审核,应届,趣头条工程师,喜欢开源,Gev作者,擅长网络编程与表情包。 27 | 28 | 29 | ## 分享时间 30 | 31 | 2020-03-12 21:00:00 UTC+8 32 | 33 | ## Slides 34 | 35 | https://docs.google.com/presentation/d/1YVysPq1dByu87aGYdUVGhjyk_l6lDFw_AuHGDq3d6Bs/edit?usp=sharing 36 | 37 | ## 参考资料 38 | 39 | - Go-Micro 框架与文档:https://micro.mu/docs/ 40 | - Micro 中国站文档:https://github.com/micro-in-cn/tutorials/ 41 | 42 | ---- 43 | 44 | ## 观看视频 45 | 46 | {{< youtube id="_ZLB4BPZaks" >}} 47 | -------------------------------------------------------------------------------- /content/night/8-2018-05-31-net-http-part2.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第 8 期 2018-05-31 线下活动 - Go 标准包阅读 3 | date: 2018-05-31T11:49:10+08:00 4 | --- 5 | >参与人数: 10 人 6 | 7 | *Go 标准包阅读* 8 | 9 | Go 版本:go 1.10.2 10 | 11 | ### net/http 12 | 13 | - server.go 14 | 15 | ### 问题 16 | 17 | 1. 18 | 19 | ```go 20 | func (s *Server) doKeepAlives() bool { 21 | return atomic.LoadInt32(&s.disableKeepAlives) == 0 && !s.shuttingDown() 22 | } 23 | ``` 24 | 25 | 为什么要用 `atomic.LoadInt32(&s.disableKeepAlives) == 0` ? 26 | 27 | 原子操作比用锁更节约一点性能。 28 | 29 | 2. server.go#Shutdown 不保险 30 | 31 | 3. panicChan := make(chan interface{}, 1) 32 | 33 | ```go 34 | panicChan := make(chan interface{}, 1) 35 | go func() { 36 | defer func() { 37 | if p := recover(); p != nil { 38 | panicChan <- p 39 | } 40 | }() 41 | h.handler.ServeHTTP(tw, r) 42 | close(done) 43 | }() 44 | select { 45 | case p := <-panicChan: 46 | panic(p) 47 | ... 48 | ``` 49 | 50 | 外部处理就不能按照你的意愿去处理了,如果不拿出来,那么进程就挂掉了。 51 | 52 | 4. // Deprecated: ErrWriteAfterFlush is no longer used. 53 | ErrWriteAfterFlush = errors.New("unused") 54 | 55 | 5. Header() Header 注释引发的Trailer的思考? 56 | 57 |  58 |  59 |  60 | 61 | ## 观看视频 62 | 63 | {{< youtube id="U84dn76gixQ" >}} 64 | 65 | ## 延伸阅读 66 | 67 | 1. [HTTP Chunked Body/Trailer编码](http://www.unclekevin.org/?p=203) 68 | 2. [example_ResponseWriter_trailers](https://golang.org/pkg/net/http/#example_ResponseWriter_trailers) 69 | 3. [HTTP Header Trailer](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Trailer) 70 | 71 | -------------------------------------------------------------------------------- /content/night/80-2020-03-18-go2-generics.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之带你提前玩 Go 2 新特性:泛型 3 | title: 第 80 期带你提前玩 Go 2 新特性:泛型 4 | date: 2020-03-18T21:00:00+08:00 5 | author: 欧长坤 6 | --- 7 | 8 | ## 【Go 夜读】#80 带你提前玩 Go 2 新特性:泛型 9 | 10 | Go 2 的泛型到底是何方神圣? 11 | 12 | 泛型的内容不太好讲,一是因为对于熟悉泛型的人来说,Go 语言泛型的设计很好理解,几乎不需要介绍什么内容;二是因为目前 Go 语言泛型功能还不够丰富,虽然能够写出一部分泛型代码,但不够完美。 13 | 思前想后,这期分享的整体基调变成了讲述 Go 语言泛型设计的演变过程,为那些对泛型这一特性不够熟悉的人介绍 Go 语言泛型设计的变化,为什么成为了现在这个样子;并在介绍完具体设计后,通过实际编写几个例子来进一步理解目前泛型设计的优缺点。最后通过与 C++ 泛型设计的比较,来总结整个 Go 的泛型设计。 14 | 15 | ## 分享者自我介绍 16 | 17 | 欧长坤,Go 夜读 SIG 小组成员 18 | 19 | ## 分享时间 20 | 21 | 2020-03-18 21:00:00 UTC+8 22 | 23 | ## Slides 24 | 25 | https://changkun.de/s/go2generics/ 26 | 27 | ---- 28 | 29 | ## 观看视频 30 | 31 | {{< youtube id="E16Y6bI2S08" >}} 32 | -------------------------------------------------------------------------------- /content/night/81-2020-03-19-gorm-guide.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 gorm 介绍与展望 3 | title: 第 81 期 gorm 介绍与展望 4 | date: 2020-03-19T21:00:00+08:00 5 | author: Jinzhu 6 | --- 7 | 8 | ## 【Go 夜读】#81 gorm 介绍与展望 9 | 10 | 对 gorm 的使用及设计做一些相关介绍,拓展。 11 | 12 | ## 分享者自我介绍 13 | 14 | Jinzhu,gorm 作者 15 | 16 | ## 分享时间 17 | 18 | 2020-03-19 21:00:00 UTC+8 19 | 20 | ## Slides 21 | 22 | https://github.com/talkgo/night/files/4355218/GORM.pdf 23 | 24 | ---- 25 | 26 | ## 观看视频 27 | 28 | {{< youtube id="NCZHe6zb2Sg" >}} 29 | -------------------------------------------------------------------------------- /content/night/82-2020-03-21-talkgo-night-story.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之聊聊我们与 Go 夜读的故事以及效率效能学习分享 3 | title: 第 82 期聊聊我们与 Go 夜读的故事以及效率效能学习分享 4 | date: 2020-03-21T21:00:00+08:00 5 | author: Go 夜读 SIG 小组,曹春晖,John,Darren 6 | --- 7 | 8 | ## 【Go 夜读】#82 聊聊我们与 Go 夜读的故事以及效率效能学习分享 9 | 10 | ## 分享者自我介绍 11 | 12 | Go 夜读 SIG 小组,曹春晖,John,Darren 13 | 14 | ## 分享时间 15 | 16 | 2020-03-21 21:00:00 UTC+8 17 | 18 | ## 时间线 19 | 20 | 我们和 Go 夜读的故事: 21 | 00:00 22 | 23 | 印象最深的 Go 夜读分享: 24 | 04:36 25 | 26 | 欧神的日常: 27 | 17:46 28 | 29 | 你是怎么学 Go 的? 30 | 26:10 31 | 32 | 欧神 2018.03.21 学 Go 的第一天,也是 Go 夜读第 1 期的时间。 33 | 27:27 34 | 35 | 欧神谈学 Go 的方法,阅读 Go 官方文档。 36 | 28:35 37 | 38 | 推荐 Chrome 插件(Rooster, TimeYourWeb, picGo, Xnip) 39 | 36:24 40 | 41 | alfred 等效率工具: 53:58 42 | 43 | cch123: 1:06:58 44 | 45 | star 项目管理? 46 | watch 问题。。。 47 | 48 | Go 后端的发展规划: 49 | 1:15:55 50 | 51 | 如何提高自己的认知/理解能力?有没有方法?听听大家怎么说。 52 | 1:22:30 53 | 54 | 谈谈安全 55 | 1:35:30 56 | 57 | ---- 58 | 59 | ## 观看视频 60 | 61 | {{< youtube id="gk510UOJoBA" >}} 62 | -------------------------------------------------------------------------------- /content/night/83-2020-03-26-gobench.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之对 Go 程序进行可靠的性能测试 3 | title: 第 83 期对 Go 程序进行可靠的性能测试 4 | date: 2020-03-26T21:00:00+08:00 5 | author: 欧长坤 6 | --- 7 | 8 | ## 【Go 夜读】#83 对 Go 程序进行可靠的性能测试 9 | 10 | 性能测试是 Go 语言工具链中比较重要的一环。我们已经知道了如何编写一个形如 `func BenchmarkFunc(b *testing.B)` 形式的的性能测试。那他的目标是什么?是否对其进行独立运行就已经足够了?如果不是,那如何才能正确的进行性能测试?又如何判断我们性能测试得到的结果是可靠的? 11 | 12 | benchstat 作为 Go 语言工具链的一环,为我们提供了进行可靠性能测试的必要条件之一。那么 benchstat 又是什么?benchstat 能够为我们做哪些事情?它的基本原理又是什么?有了 benchstat 之后我们就可以「高枕无忧」了吗?我们还需要什么其他的工具吗? 13 | 14 | 本次分享我们将就上述这些问题展开,讨论如何在 Go 语言中进行可靠的性能测试。 15 | 16 | ## 大纲 17 | 18 | - 准备可靠的测试环境 19 | - benchstat 20 | - 例子与实践 21 | - 对代码块进行性能调优 22 | - Benchmark 的正确性分析 23 | - 其他的影响因素 24 | - benchstat 中假设检验的原理 25 | - 局限性及应对措施 26 | 27 | ## 分享者自我介绍 28 | 29 | 欧长坤,Go 夜读 SIG 小组成员 30 | 31 | ## 分享时间 32 | 33 | 2020-03-26 21:00:00 UTC+8 34 | 35 | ## 时间线 36 | 37 | - 准备可靠的测试环境 00:00 38 | - benchstat 09:25 39 | - benchstat 原理 24:15 40 | - runtime.memequal 的源码阅读 40:20 41 | - 假设检验的原理 45:50 42 | - 局限于应对措施 perflock 1:07:25 43 | - perflock 原理 1:11:46 44 | - 红黑树 1:24:40 45 | - 手把手教你画出高大尚的图表📈1:28:30 46 | - terminal 吐血分享 1:29:50 47 | - Go map 的一个问题 1:33:50 48 | - 数学的重要性 1:35:00 49 | - Github 案例剖析答疑 1:35:50 50 | 51 | ## Slides 52 | 53 | https://changkun.de/s/gobench/ 54 | 55 | ---- 56 | 57 | ## 观看视频 58 | 59 | {{< youtube id="RXM9cDzWZME" >}} 60 | -------------------------------------------------------------------------------- /content/night/84-2020-04-02-go-aligned.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之图解 Go 内存对齐 3 | title: 第 84 期图解 Go 内存对齐 4 | date: 2020-04-02T21:00:00+08:00 5 | author: 苗蕾@ThoutWorks 6 | --- 7 | 8 | ## 【Go 夜读】#84 图解 Go 内存对齐 9 | 10 | 关于内存对齐总会有各种声音?为什么要对齐,怎么对齐,不对齐有什么影响么? 11 | 12 | 这些声音可以离我们很远,也可以很近,比如: 13 | 14 | 当你想弄明白WaitGroup.state1为什么是[3]uint32而不是[12]byte 15 | 当你想知道struct是否占用内存是否合理 16 | 当你不希望在32位系统上原子操作int64|uint64时发生panic 17 | 当你闲着没事就是想读读源码提升下逼格。。。 18 | 本次分享借自己研究内存对齐的一些代码及源码示例,为大家带来Go里边的内存对齐是什么样的,以及如何利用内存对齐优化数据结构,提高代码的平台兼容性。 19 | 20 | ## 大纲 21 | 22 | - 了解内存对齐的收益 23 | - 为什么要对齐 24 | - 怎么对齐: 25 | - 数据结构对齐 26 | - 内存地址对齐 27 | - 64位字的安全访问保证(32位平台) 28 | 29 | ## 分享者自我介绍 30 | 31 | 苗蕾,Thoughtworks,搬砖工。 32 | 33 | ## 分享时间 34 | 35 | 2020-04-02 21:00:00 UTC+8 36 | 37 | ## Slides 38 | 39 | https://docs.google.com/presentation/d/1XUA8WfgTHCF_8XdfPEuNvs-WZ0DshFHKFEEqHRd3Tzg/edit?usp=sharing 40 | 41 | ---- 42 | 43 | ## 观看视频 44 | 45 | {{< youtube id="8a2G2MXRUxw" >}} 46 | -------------------------------------------------------------------------------- /content/night/85-2020-04-16-douyu-confgo.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之斗鱼 Minerva 配置中心设计与实现 3 | title: 第 85 期斗鱼 Minerva 配置中心设计与实现 4 | date: 2020-04-16T21:00:00+08:00 5 | author: 杜旻翔@斗鱼 6 | --- 7 | 8 | ## 【Go 夜读】#85 斗鱼 Minerva 配置中心设计与实现 9 | 10 | 介绍斗鱼 Minerva 配置中心的功能,以及后续的开源计划。 11 | 12 | ## 大纲 13 | 14 | 1. 为什么需要配置中心 15 | 2. 什么是 Confgo 16 | 3. 为什么选择 Confgo 17 | 4. Confgo 技术点 18 | 5. Confgo 概览 19 | 20 | ## 分享者自我介绍 21 | 22 | 杜旻翔,武汉斗鱼科技有限公司,研发工程师,三年 Go 语言开发经验。 23 | 24 | ## 分享时间 25 | 26 | 2020-04-16 21:00:00 UTC+8 27 | 28 | ## Slides 29 | 30 | https://docs.google.com/presentation/d/1nNjE5KjAsi-vpDtwNhdMJkLG8Uvnk1SYLWXJnI8n8mk/edit?usp=sharing 31 | 32 | ---- 33 | 34 | ## 观看视频 35 | 36 | {{< youtube id="i-Q3x1PBqD0" >}} 37 | -------------------------------------------------------------------------------- /content/night/86-2020-04-23-go-unsafe-pointer.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 Go 中非类型安全指针相关的事实和使用规则 3 | title: 第 86 期 Go 中非类型安全指针相关的事实和使用规则 4 | date: 2020-04-23T21:00:00+08:00 5 | author: 杜旻翔@斗鱼 6 | --- 7 | 8 | ## 【Go 夜读】#86 Go 中非类型安全指针相关的事实和使用规则 9 | 10 | Go 是一门支持自动垃圾回收和自动保护内存安全的语言。但是有时候 Go 运行时(runtime)提供的安全机制限制了某些细节和功能不能采用效率最高的方法来实现。非类型安全指针可以帮助我们绕开这些限制,但同时也打破了 Go 运行时处心积虑构建起来的安全屏障。在使用非类型安全指针时,我们必须谨慎地遵照 Go 官方文档中提出的建议,否则将产生一些很难觉察和很难定位的 bug。 11 | 12 | 本次分享将讲解和非类型安全指针相关的事实/规则,以及使用中的注意事项。 13 | 14 | ## 大纲 15 | 16 | - 非类型安全指针相关的事实 17 | - 非类型安全指针相关的类型转换规则 18 | - 非类型安全指针相关的使用规则 19 | 20 | ## 分享者自我介绍 21 | 22 | 老貘,《Go 101》一书作者。 23 | 24 | ## 分享时间 25 | 26 | 2020-04-23 21:00 UTC+8 27 | 28 | ## Slides 29 | 30 | https://github.com/yaxinlx/go-nightreading-unsafe 31 | 32 | ---- 33 | 34 | ## 观看视频 35 | 36 | {{< youtube id="a_9oLmeFvwk" >}} 37 | -------------------------------------------------------------------------------- /content/night/87-2020-04-29-goland-tips.md: -------------------------------------------------------------------------------- 1 | --- 2 | desc: Go 夜读之 JetBrains GoLand 2020.1 新特性介绍 3 | title: 第 87 期 JetBrains GoLand 2020.1 新特性介绍 4 | date: 2020-04-29T21:00:00+08:00 5 | author: Florin Pățan & 范圣佑 6 | --- 7 | 8 | ## 【Go 夜读】#87 JetBrains GoLand 2020.1 新特性介绍 9 | 10 | 由 JetBrains 打造的 GoLand 是专门为 Gopher 量身定制的全功能 IDE,若能善用其特性将可大大提升工作产能。随着 2020.1 版本的更新,带来了更多方便的新特性。距离上次分享已间隔将近一年,这次将专注为大家演示这些新引入的特性,希望将效率再往上提升一个层次。 11 | 12 | ## 大纲 13 | 14 | 1. GoLand 基本使用介绍; 15 | 2. Go 高效实战开发; 16 | 3. 授权码释疑; 17 | 18 | ## 分享者自我介绍 19 | 20 | Florin Pățan (以英语宣讲) 21 | GoLand 技术布道师 @JetBrains 22 | Florin 是资深 Gopher,参与过众多高性能、分散式的项目,目前在 JetBrains 担任 Goland 技术布道师。他在全世界有 Gopher 的地方出没,协助 Gopher 们能更高效的运用 Go 语言及 GoLand 做开发。 23 | 24 | 范圣佑 (协助翻译) 25 | 技术布道师 @JetBrains 26 | 圣佑是 JetBrains 技术布道师,负责推广 JetBrians 相关技术与产品,包括:Kotlin 编程语言、 IntelliJ IDEA 系列 IDE 及 YouTrack、TeamCity、Upsource 等团队合作解决方案,协助开发者善用工具辅助来提升生产力,同时维护代码品质。 27 | 28 | ## 分享时间 29 | 30 | 2020-04-29 21:00 UTC+8 31 | 32 | ## 参考资料 33 | 34 | https://www.jetbrains.com/go/whatsnew 35 | 36 | ---- 37 | 38 | ## 观看视频 39 | 40 | {{< youtube id="QGEtbFtLMAc" >}} 41 | -------------------------------------------------------------------------------- /content/night/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Go 源码阅读" 3 | date: 2018-11-15T12:32:37+08:00 4 | weight: 2 5 | --- 6 | -------------------------------------------------------------------------------- /content/night/other/16-2018-09-06-faas.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkgo/night/75e5c3e44086f2c2c3f24fc44e7c5e57e0e856cc/content/night/other/16-2018-09-06-faas.pdf -------------------------------------------------------------------------------- /content/night/other/16-2018-09-06-openfaas-guide.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第16期 OpenFaas 介绍及源码分析 3 | date: 2018-09-06T11:49:10+08:00 4 | --- 5 | ### 关于我 6 | 7 | 网名: Lucas 8 | 9 | Github:https://github.com/zhenfeng-zhu 10 | 11 | 博客:https://zhenfeng-zhu.github.io/ 12 | 13 | 知乎:https://www.zhihu.com/people/zhu-zhen-feng-96/activities 14 | 15 | 专栏:https://zhuanlan.zhihu.com/openfaas-cn 16 | 17 | 微信:zhuzhenfeng1993 18 | 19 | ### 主要内容 20 | 21 | - OpenFaaS的简介 22 | 23 | - OpenFaaS的快速入门 24 | 25 | - OpenFaaS的基础组件 26 | 27 | - OpenFaaS的源码分析 28 | 29 | - OpenFaaS的定制 30 | 31 | ## 观看视频 32 | 33 | {{< youtube id="bZtgrAVR9HQ" >}} 34 | -------------------------------------------------------------------------------- /content/night/other/16-2018-09-06-quick-start.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第 16 期 Go 快速入门 3 | date: 2018-09-06T11:49:10+08:00 4 | --- 5 | 6 | 创建一个新函数 7 | 8 | ``` 9 | faas-cli new --lang node hell-node 10 | ``` 11 | 12 | 构建函数 13 | 14 | ``` 15 | faas-cli build -f hello-node.yml 16 | ``` 17 | 18 | 推送函数到docker仓库 19 | 20 | ``` 21 | faas-cli push -f hello-node.yml 22 | ``` 23 | 24 | 部署函数 25 | 26 | ``` 27 | faas-cli deploy -f hello-node.yml 28 | ``` 29 | 30 | 稍等几秒钟,等待部署,然后就可以从postman发送get或者post请求。 31 | 32 |  33 | 34 | 在rancher中的状态 35 | 36 |  37 | 38 | 函数的状态 39 | 40 |  41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /content/night/other/2018-08-17-sync-pool-reading.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkgo/night/75e5c3e44086f2c2c3f24fc44e7c5e57e0e856cc/content/night/other/2018-08-17-sync-pool-reading.pdf -------------------------------------------------------------------------------- /content/night/other/sync-pool-demo/cmd/makeslice.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | a := make([]int64, 0, 32) 7 | fmt.Println(cap(a), len(a)) 8 | 9 | for i := 0; i < 30; i++ { 10 | a = append(a, 1) 11 | fmt.Println(cap(a), len(a)) 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /content/night/other/sync-pool-demo/demo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "log" 7 | "net/http" 8 | "sync" 9 | ) 10 | 11 | // 临时对象池 12 | var p = sync.Pool{ 13 | New: func() interface{} { 14 | buffer := make([]byte, 256) 15 | return &buffer 16 | }, 17 | } 18 | 19 | //wg 是一个指针类型,必须是一个内存地址 20 | func readContent(wg *sync.WaitGroup) { 21 | defer wg.Done() 22 | resp, err := http.Get("http://www.baidu.com") 23 | if err != nil { 24 | // handle error 25 | } 26 | 27 | defer resp.Body.Close() 28 | 29 | byteSlice := p.Get().(*[]byte) //类型断言 30 | 31 | numBytesReadAtLeast, err := io.ReadFull(resp.Body, *byteSlice) 32 | if err != nil { 33 | // handle error 34 | } 35 | 36 | p.Put(byteSlice) 37 | 38 | log.Printf("Number of bytes read: %d\n", numBytesReadAtLeast) 39 | fmt.Println(string((*byteSlice)[:256])) 40 | } 41 | 42 | func main() { 43 | var wg sync.WaitGroup 44 | 45 | for i := 0; i < 1000; i++ { 46 | wg.Add(1) 47 | go readContent(&wg) 48 | } 49 | 50 | wg.Wait() 51 | fmt.Println("end...") 52 | } 53 | -------------------------------------------------------------------------------- /content/night/other/sync-pool-demo/demo2/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "log" 7 | "net/http" 8 | "sync" 9 | ) 10 | 11 | var mu sync.Mutex 12 | var holder map[string]bool = make(map[string]bool) 13 | 14 | // 临时对象池 15 | var p = sync.Pool{ 16 | New: func() interface{} { 17 | buffer := make([]byte, 256) 18 | return &buffer 19 | }, 20 | } 21 | 22 | //wg 是一个指针类型,必须是一个内存地址 23 | func readContent(wg *sync.WaitGroup) { 24 | defer wg.Done() 25 | resp, err := http.Get("http://my.oschina.net/xinxingegeya/home") 26 | if err != nil { 27 | // handle error 28 | } 29 | 30 | defer resp.Body.Close() 31 | 32 | byteSlice := p.Get().(*[]byte) //类型断言 33 | 34 | key := fmt.Sprintf("%p", byteSlice) 35 | //////////////////// 36 | // 互斥锁,实现同步操作 37 | mu.Lock() 38 | _, ok := holder[key] 39 | if !ok { 40 | holder[key] = true 41 | } 42 | mu.Unlock() 43 | //////////////////// 44 | 45 | numBytesReadAtLeast, err := io.ReadFull(resp.Body, *byteSlice) 46 | if err != nil { 47 | // handle error 48 | } 49 | 50 | p.Put(byteSlice) 51 | 52 | log.Printf("Number of bytes read: %d\n", numBytesReadAtLeast) 53 | fmt.Println(string((*byteSlice)[:256])) 54 | } 55 | 56 | func main() { 57 | var wg sync.WaitGroup 58 | 59 | for i := 0; i < 1000; i++ { 60 | wg.Add(1) 61 | go readContent(&wg) 62 | } 63 | 64 | wg.Wait() 65 | 66 | fmt.Println(len(holder)) 67 | 68 | for key, val := range holder { 69 | fmt.Println("Key:", key, "Value:", val) 70 | } 71 | 72 | fmt.Println("end...") 73 | } 74 | -------------------------------------------------------------------------------- /content/night/other/sync-pool-demo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "runtime" 6 | "sync" 7 | ) 8 | 9 | func main() { 10 | p := &sync.Pool{ 11 | New: func() interface{} { 12 | return 0 13 | }, 14 | } 15 | a := p.Get().(int) 16 | p.Put(1) 17 | b := p.Get().(int) 18 | log.Println(a, b) 19 | p.Put(3) 20 | p.Put(4) 21 | p.Put(5) 22 | log.Println(p.Get()) //返回 3 4 5中的任意一个。 23 | //主动调用GC pool中对象会被清理掉 24 | runtime.GC() 25 | p.Put(2) 26 | c := p.Get().(int) 27 | log.Println(c) 28 | } 29 | -------------------------------------------------------------------------------- /content/night/other/zap-learn/go.mod: -------------------------------------------------------------------------------- 1 | module zap-learn 2 | 3 | go 1.15 4 | 5 | require ( 6 | go.uber.org/multierr v1.6.0 // indirect 7 | go.uber.org/zap v1.16.0 8 | ) 9 | -------------------------------------------------------------------------------- /content/night/other/zap-learn/logger/logger_test.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestFinfo(t *testing.T) { 8 | FInfo("~~~prefix", "key", "value", "key2", "value2", "key3", "value3", "key4", "value4") 9 | } 10 | 11 | func init() { 12 | //if err := config.InitConfig("../assets/config.yaml"); err != nil { 13 | // panic(err) 14 | //} 15 | 16 | // init logger 17 | if err := Setup(); err != nil { 18 | panic(err) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /content/night/other/zap-learn/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "zap-learn/logger" 5 | ) 6 | 7 | func main() { 8 | if err := logger.Setup(); err != nil { 9 | logger.Error(err) 10 | return 11 | } 12 | logger.FDebug("prefix", "key1", "value1", "key2", "value2") 13 | logger.FInfo("Base setup", "config path") 14 | } 15 | -------------------------------------------------------------------------------- /content/other/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ../../CONTRIBUTING.md -------------------------------------------------------------------------------- /content/other/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "其他" 3 | date: 2018-11-15T12:32:37+08:00 4 | weight: 10 5 | --- 6 | -------------------------------------------------------------------------------- /content/other/goland-help.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Go 开发工具 3 | date: 2018-12-06T00:00:00+08:00 4 | --- 5 | 6 | ## GoLand 7 | 8 | ### GoLand 怎么修改主题样式? 9 | 10 | Preferences...-->Editor-->Color Scheme-->选择你喜欢的主题,然后点击 Apply,即可实时查看。 11 | 12 | ### GoLand 下载新的主题 13 | 14 | Plugins-->material Theme UI-->点击 Install,然后重启 GoLand 即可。 15 | 16 | ### GoLand 函数 doc 能不能悬停提示? 17 | 18 | Editor-->General-->Other -> Show quick documentation on mouse move Delay:500 ms,点击应用即可查看。 19 | 20 | ### GoLand 保存时自动格式化 21 | 22 | GoLand/Intellij Idea 可以帮助我们在保存时自动格式化代码. 23 | 24 | Preferences...-->Tools-->File watchers-->go fmt/go imports,点击 OK 即可生效。 25 | 26 | ### 用了 GoLand 会将自己的配置文件覆盖,怎么办? 27 | 28 | 配置选项取消勾选就行: 29 | 30 | Preferences...-->Tools-->Terminal-->将 shell integration 打勾取消,点击 OK 即可生效。 31 | 32 | ### GoLand 怎么选中光标及其往后的所有内容? 33 | 34 | VS Code 里面是通过 command+shift+向下箭头。 35 | 36 | ### GoLand 怎么到文件首行? 37 | 38 | VS Code 里面是通过 command+向上箭头。 39 | 40 | 41 | -------------------------------------------------------------------------------- /content/proposal/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "建议" 3 | date: 2018-11-15T12:32:37+08:00 4 | weight: 9 5 | --- 6 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # 项目实践 2 | 3 | 1. [Gin 开发实践](./gin_examples) 4 | -------------------------------------------------------------------------------- /examples/gin_examples/.gitignore: -------------------------------------------------------------------------------- 1 | *log 2 | volumes 3 | -------------------------------------------------------------------------------- /examples/gin_examples/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkgo/night/75e5c3e44086f2c2c3f24fc44e7c5e57e0e856cc/examples/gin_examples/.gitkeep -------------------------------------------------------------------------------- /examples/gin_examples/ENDPOINTS.md: -------------------------------------------------------------------------------- 1 | # Endpoints 2 | 3 | ## Registration 4 | 5 | - `/api/register` Register a new user. 6 | 7 | ``` 8 | curl -XPOST -d '{ "name": "heisenberg", "email": "heisenberg@gmail.com", "password": "saymyname!" }' 'http://localhost:8080/api/register' 9 | ``` 10 | 11 | - `/api/login` Login an existing user. 12 | 13 | ``` 14 | curl -XPOST -d '{ "email": "heisenberg@gmail.com", "password": "saymyname!" }' 'http://localhost:8080/api/login' 15 | ``` 16 | 17 | - `/api/logout` Logout current user. 18 | 19 | ``` 20 | curl -XPOST 'http://localhost:8080/api/logout' 21 | ``` 22 | 23 | ## User 24 | 25 | - `/api/v1/me` GET own user (based on SessionToken). 26 | 27 | ``` 28 | curl -v --cookie "sessionID=710ddd62-4f10-4bf3-8f30-325f7f4a297f" 'http://localhost:8080/api/v1/me' 29 | ``` 30 | 31 | 32 | - `/api/v1/users/:id` GET users. 33 | 34 | ``` 35 | curl -v --cookie "sessionID=710ddd62-4f10-4bf3-8f30-325f7f4a297f" 'http://localhost:8080/api/v1/users/1' 36 | ``` 37 | -------------------------------------------------------------------------------- /examples/gin_examples/Makefile: -------------------------------------------------------------------------------- 1 | run: 2 | @echo "=============starting server=============" 3 | go run cmd/server/main.go 4 | 5 | test: 6 | @echo "=============running test=============" 7 | go test ./... 8 | 9 | docker-build: 10 | @echo "=============building image=============" 11 | docker build . -t ginexamples-backend:`git rev-parse HEAD` 12 | 13 | compose-up: 14 | @echo "=============starting gollery locally=============" 15 | docker-compose -f docker-compose-dev.yml up 16 | 17 | compose-logs: 18 | docker-compose logs -f 19 | 20 | compose-down: 21 | docker-compose down 22 | 23 | pg-up: 24 | @echo "=============running a temporary postgres=============" 25 | docker run --rm --name pg-docker -e POSTGRES_USER=postgres -e POSTGRES_DB=ginexamples -d -p 5432:5432 postgres 26 | 27 | pg-down: 28 | @echo "=============stopping the temporary postgres=============" 29 | docker stop pg-docker 30 | 31 | docker-reset: 32 | @echo "=============resetting docker=============" 33 | docker system prune -af 34 | -------------------------------------------------------------------------------- /examples/gin_examples/README.md: -------------------------------------------------------------------------------- 1 | # Gin Example 2 | 3 | **[Endpoints](ENDPOINTS.md)** 4 | 5 | ## How to Start 6 | 7 | - `make test` 8 | - `make pg-up` 9 | - `make run` 10 | - `make pg-down` 11 | 12 | ## Development Flow 13 | 14 | ``` 15 | 1. Modfiy interfaces 16 | 2. Modfiy services 17 | 3. Modfiy repositories 18 | 4. Modfiy handlers 19 | 5. Modfiy routes 20 | ``` 21 | 22 | ## Test Flow 23 | 24 | ``` 25 | 1. Modfiy mocks 26 | 2. Modfiy handler_test 27 | ``` 28 | 29 | **Note** 30 | 31 | 1. Handlers only interact with Services 32 | 2. Services interact with Repository (DB) 33 | -------------------------------------------------------------------------------- /examples/gin_examples/cmd/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "ginexamples/pkg/config" 5 | "ginexamples/pkg/http" 6 | "ginexamples/pkg/postgres" 7 | "ginexamples/pkg/service/userservice" 8 | "io" 9 | "log" 10 | "os" 11 | ) 12 | 13 | func main() { 14 | c := config.GetConfig() 15 | postgresConfig := postgres.DBConfig{ 16 | Host: c.PGHost, 17 | Port: c.PGPort, 18 | User: c.PGUser, 19 | Password: c.PGPassword, 20 | Name: c.PGDBName, 21 | } 22 | 23 | repository := postgres.Initialize(postgresConfig) 24 | repository.AutoMigrate() 25 | 26 | var logDst io.Writer 27 | if c.LogFile == "" { 28 | logDst = os.Stdout 29 | } else { 30 | file, err := os.OpenFile(c.LogFile, os.O_APPEND|os.O_CREATE, 0600) 31 | if err != nil { 32 | log.Fatalf("error opening logfile %s: %v", c.LogFile, err) 33 | } 34 | defer file.Close() 35 | logDst = file 36 | } 37 | 38 | server := http.AppServer{ 39 | Logger: log.New(logDst, "", log.LstdFlags), 40 | UserService: userservice.New(repository.UserRepository), 41 | } 42 | server.Run() 43 | } 44 | -------------------------------------------------------------------------------- /examples/gin_examples/docker-compose-dev.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | db: 5 | container_name: postgres 6 | image: postgres 7 | restart: always 8 | ports: 9 | - 5432:5432 10 | volumes: 11 | - ./volumes/postgresql:/var/lib/postgresql/data 12 | environment: 13 | - POSTGRES_USER=postgres 14 | - POSTGRES_DB=ginexamples 15 | -------------------------------------------------------------------------------- /examples/gin_examples/go.mod: -------------------------------------------------------------------------------- 1 | module ginexamples 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/denisenkom/go-mssqldb v0.0.0-20190412015539-88dfc25f102b // indirect 7 | github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 // indirect 8 | github.com/gin-gonic/gin v1.9.1 9 | github.com/go-sql-driver/mysql v1.4.1 // indirect 10 | github.com/gofrs/uuid v3.2.0+incompatible 11 | github.com/jinzhu/gorm v1.9.2 12 | github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a // indirect 13 | github.com/jinzhu/now v1.0.0 // indirect 14 | github.com/kr/pretty v0.3.0 // indirect 15 | github.com/lib/pq v1.0.0 // indirect 16 | github.com/mattn/go-sqlite3 v1.10.0 // indirect 17 | github.com/pkg/errors v0.8.1 18 | github.com/rogpeppe/go-internal v1.8.0 // indirect 19 | github.com/stretchr/testify v1.8.3 20 | golang.org/x/crypto v0.35.0 21 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect 22 | ) 23 | -------------------------------------------------------------------------------- /examples/gin_examples/pkg/auth/auth.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import "golang.org/x/crypto/bcrypt" 4 | 5 | type Authenticator struct{} 6 | 7 | func (a *Authenticator) Hash(password string) (string, error) { 8 | bytePwd := []byte(password) 9 | hash, err := bcrypt.GenerateFromPassword(bytePwd, bcrypt.DefaultCost) 10 | if err != nil { 11 | return "", err 12 | } 13 | 14 | return string(hash), nil 15 | } 16 | 17 | func (a *Authenticator) CompareHash(hashedPassword string, plainPassword string) error { 18 | err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(plainPassword)) 19 | if err != nil { 20 | return err 21 | } 22 | 23 | return nil 24 | } 25 | -------------------------------------------------------------------------------- /examples/gin_examples/pkg/auth/auth_test.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "golang.org/x/crypto/bcrypt" 8 | ) 9 | 10 | func TestAuthenticationProvider_HashAndSalt(t *testing.T) { 11 | t.Parallel() 12 | var testCases = []struct { 13 | name string 14 | input string 15 | }{ 16 | {"expected", "password"}, 17 | {"empty", ""}, 18 | } 19 | 20 | authenticator := Authenticator{} 21 | 22 | for _, v := range testCases { 23 | t.Run(v.name, func(t *testing.T) { 24 | hash, err := authenticator.Hash(v.input) 25 | assert.Nil(t, err, "should not cause error") 26 | assert.NotEmptyf(t, hash, "hashes do not match") 27 | 28 | err = bcrypt.CompareHashAndPassword([]byte(hash), []byte(v.input)) 29 | assert.Nil(t, err, "passwords do not match") 30 | }) 31 | } 32 | } 33 | 34 | func TestAuthenticator_CompareWithHash(t *testing.T) { 35 | t.Parallel() 36 | var testCases = []struct { 37 | name string 38 | input string 39 | reference string 40 | }{ 41 | {"expected", "password", "password"}, 42 | {"empty", "", ""}, 43 | {"error", "password", "drowssap"}, 44 | } 45 | 46 | authenticator := Authenticator{} 47 | 48 | for _, v := range testCases { 49 | t.Run(v.name, func(t *testing.T) { 50 | hash, err := authenticator.Hash(v.reference) 51 | assert.Nil(t, err, "should not cause error") 52 | assert.NotEmptyf(t, hash, "hashes do not match") 53 | 54 | err = authenticator.CompareHash(hash, v.input) 55 | 56 | if v.input != v.reference { 57 | assert.Error(t, err, "should cause an error") 58 | return 59 | } 60 | assert.Nil(t, err, "should not cause error") 61 | }) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /examples/gin_examples/pkg/auth/sessionId.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/gofrs/uuid" 7 | ) 8 | 9 | func (Authenticator) SessionID() string { 10 | u2, err := uuid.NewV4() 11 | if err != nil { 12 | log.Fatalf("failed to generate UUID: %v", err) 13 | } 14 | return u2.String() 15 | } 16 | -------------------------------------------------------------------------------- /examples/gin_examples/pkg/auth/sessionId_test.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/gofrs/uuid" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestAuthenticator_SessionID(t *testing.T) { 11 | t.Parallel() 12 | authenticator := Authenticator{} 13 | sessionID := authenticator.SessionID() 14 | 15 | id, err := uuid.FromString(sessionID) 16 | assert.Nil(t, err, "should not cause error") 17 | assert.Equal(t, byte(4), id.Version(), "should create UUID v4") 18 | } 19 | -------------------------------------------------------------------------------- /examples/gin_examples/pkg/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "os" 5 | ) 6 | 7 | // Config contains all the environment varialbes. 8 | type Config struct { 9 | Port string 10 | Env string 11 | PGHost string 12 | PGPort string 13 | PGUser string 14 | PGPassword string 15 | PGDBName string 16 | LogFile string 17 | } 18 | 19 | func (c Config) IsProd() bool { 20 | return c.Env == "prod" 21 | } 22 | 23 | // GetConfig returns the environment varialbes. 24 | func GetConfig() Config { 25 | port, ok := os.LookupEnv("PORT") 26 | if !ok { 27 | port = "8080" 28 | } 29 | 30 | env, ok := os.LookupEnv("ENV") 31 | if !ok { 32 | env = "development" 33 | } 34 | 35 | pgHost, ok := os.LookupEnv("PG_HOST") 36 | if !ok { 37 | pgHost = "localhost" 38 | } 39 | 40 | pgPort, ok := os.LookupEnv("PG_PORT") 41 | if !ok { 42 | pgPort = "5432" 43 | } 44 | 45 | pgUser, ok := os.LookupEnv("PG_USER") 46 | if !ok { 47 | pgUser = "postgres" 48 | } 49 | 50 | pgPassword, ok := os.LookupEnv("PG_PASSWORD") 51 | if !ok { 52 | pgPassword = "" 53 | } 54 | 55 | pgDBName, ok := os.LookupEnv("PG_DB_NAME") 56 | if !ok { 57 | pgDBName = "ginexamples" 58 | } 59 | 60 | logFile, ok := os.LookupEnv("LOGFILE") 61 | if !ok { 62 | logFile = "" 63 | } 64 | 65 | return Config{ 66 | Port: port, 67 | Env: env, 68 | PGHost: pgHost, 69 | PGPort: pgPort, 70 | PGUser: pgUser, 71 | PGPassword: pgPassword, 72 | PGDBName: pgDBName, 73 | LogFile: logFile, 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /examples/gin_examples/pkg/config/config_test.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestGetConfig(t *testing.T) { 11 | var envs = []struct { 12 | key string 13 | value string 14 | }{ 15 | {"PORT", "testport"}, 16 | {"ENV", "testenv"}, 17 | {"PG_HOST", "testhost"}, 18 | {"PG_PORT", "testport"}, 19 | {"PG_USER", "testuser"}, 20 | {"PG_PASSWORD", "testpass"}, 21 | {"PG_DB_NAME", "testname"}, 22 | {"LOGFILE", "backend.log"}, 23 | } 24 | 25 | var testCases = []struct { 26 | name string 27 | unset bool 28 | expected Config 29 | }{ 30 | {"set", false, 31 | Config{ 32 | "testport", 33 | "testenv", 34 | "testhost", 35 | "testport", 36 | "testuser", 37 | "testpass", 38 | "testname", 39 | "backend.log", 40 | }}, 41 | {"unset", true, 42 | Config{ 43 | "8080", 44 | "development", 45 | "localhost", 46 | "5432", 47 | "postgres", 48 | "", 49 | "ginexamples", 50 | "", 51 | }}, 52 | } 53 | 54 | for _, v := range testCases { 55 | t.Run(v.name, func(t *testing.T) { 56 | for _, e := range envs { 57 | os.Unsetenv(e.key) 58 | if !v.unset { 59 | os.Setenv(e.key, e.value) 60 | } 61 | } 62 | 63 | c := GetConfig() 64 | cExpected := v.expected 65 | assert.Equal(t, cExpected, c, "config does not match expected one") 66 | }) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /examples/gin_examples/pkg/http/middleware.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "ginexamples" 5 | "log" 6 | "net/http" 7 | 8 | "github.com/gin-gonic/gin" 9 | ) 10 | 11 | func NewAuthMiddleware(provider ginexamples.UserAuthenticationProvider) gin.HandlerFunc { 12 | return func(c *gin.Context) { 13 | sessionID, err := c.Cookie("sessionID") 14 | if err != nil { 15 | c.AbortWithStatus(http.StatusForbidden) 16 | return 17 | } 18 | 19 | user, err := provider.CheckAuthentication(sessionID) 20 | if err != nil { 21 | c.AbortWithStatus(http.StatusForbidden) 22 | return 23 | } 24 | 25 | c.Set("userID", user.ID) 26 | c.Next() 27 | } 28 | } 29 | 30 | func CORS() gin.HandlerFunc { 31 | return func(c *gin.Context) { 32 | c.Writer.Header().Set("Access-Control-Allow-Origin", "http://localhost:8080") 33 | c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") 34 | c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding") 35 | c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") 36 | 37 | if c.Request.Method == "OPTIONS" { 38 | c.AbortWithStatus(http.StatusOK) 39 | return 40 | } 41 | 42 | c.Next() 43 | } 44 | } 45 | 46 | func Logger(l *log.Logger) gin.HandlerFunc { 47 | return func(c *gin.Context) { 48 | l.Printf("%s: %s %s", c.Request.RemoteAddr, c.Request.Method, c.Request.URL.Path) 49 | c.Next() 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /examples/gin_examples/pkg/http/routes.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | func (a *AppServer) privateRoutes(router *gin.RouterGroup) { 8 | router.GET("me", a.GetMeHandler) 9 | router.GET("users/:id", a.GetUserHandler) 10 | } 11 | 12 | func (a *AppServer) publicRoutes(router *gin.RouterGroup) { 13 | router.POST("/register", a.RegisterUserHandler) 14 | router.POST("/login", a.LoginUserHandler) 15 | router.POST("/logout", a.LogoutUserHandler) 16 | } 17 | -------------------------------------------------------------------------------- /examples/gin_examples/pkg/http/server.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "ginexamples" 5 | "log" 6 | 7 | "github.com/gin-gonic/gin" 8 | ) 9 | 10 | // AppServer contains the information to run a server. 11 | type AppServer struct { 12 | UserService ginexamples.UserService 13 | Logger *log.Logger 14 | route *gin.Engine 15 | } 16 | 17 | func (a *AppServer) initialize() { 18 | gin.DisableConsoleColor() 19 | route := gin.New() 20 | public := route.Group("/api", Logger(a.Logger), CORS()) 21 | private := route.Group("/api/v1", Logger(a.Logger), CORS(), NewAuthMiddleware(a.UserService)) 22 | a.publicRoutes(public) 23 | a.privateRoutes(private) 24 | 25 | a.route = route 26 | } 27 | 28 | // Run will start the gin server. 29 | func (a *AppServer) Run() { 30 | a.initialize() 31 | a.route.Run() 32 | } 33 | -------------------------------------------------------------------------------- /examples/gin_examples/pkg/mock/repository.go: -------------------------------------------------------------------------------- 1 | package mock 2 | 3 | import "ginexamples" 4 | 5 | type UserRepository struct { 6 | StoreFn func(user *ginexamples.User) error 7 | StoreFnInvoked bool 8 | 9 | UpdateFn func(user *ginexamples.User) error 10 | UpdateFnInvoked bool 11 | 12 | FindFn func(id string) (*ginexamples.User, error) 13 | FindFnInvoked bool 14 | 15 | FindByEmailFn func(email string) (*ginexamples.User, error) 16 | FindByEmailFnInvoked bool 17 | 18 | FindBySessionIDFn func(sessionID string) (*ginexamples.User, error) 19 | FindBySessionIDFnInvoked bool 20 | } 21 | 22 | func (uRM *UserRepository) Store(user *ginexamples.User) error { 23 | uRM.StoreFnInvoked = true 24 | return uRM.StoreFn(user) 25 | } 26 | 27 | func (uRM *UserRepository) Update(user *ginexamples.User) error { 28 | uRM.UpdateFnInvoked = true 29 | return uRM.UpdateFn(user) 30 | } 31 | 32 | func (uRM *UserRepository) Find(id string) (*ginexamples.User, error) { 33 | uRM.FindFnInvoked = true 34 | return uRM.FindFn(id) 35 | } 36 | 37 | func (uRM *UserRepository) FindByEmail(email string) (*ginexamples.User, error) { 38 | uRM.FindByEmailFnInvoked = true 39 | return uRM.FindByEmailFn(email) 40 | } 41 | 42 | func (uRM *UserRepository) FindBySessionID(sessionID string) (*ginexamples.User, error) { 43 | uRM.FindBySessionIDFnInvoked = true 44 | return uRM.FindBySessionIDFn(sessionID) 45 | } 46 | -------------------------------------------------------------------------------- /examples/gin_examples/pkg/postgres/postgres.go: -------------------------------------------------------------------------------- 1 | package postgres 2 | 3 | import ( 4 | "fmt" 5 | "ginexamples" 6 | 7 | "github.com/jinzhu/gorm" 8 | _ "github.com/jinzhu/gorm/dialects/postgres" 9 | ) 10 | 11 | // DBConfig contains the environment varialbes requirements to initialize postgres. 12 | type DBConfig struct { 13 | Host string 14 | Port string 15 | User string 16 | Password string 17 | Name string 18 | } 19 | 20 | func (c DBConfig) connectionInfo() string { 21 | if c.Password == "" { 22 | return fmt.Sprintf("host=%s port=%s user=%s dbname=%s "+ 23 | "sslmode=disable", c.Host, c.Port, c.User, c.Name) 24 | } 25 | return fmt.Sprintf("host=%s port=%s user=%s password=%s "+ 26 | "dbname=%s sslmode=disable", c.Host, c.Port, c.User, 27 | c.Password, c.Name) 28 | } 29 | 30 | // Repository contains information for every repositories. 31 | type Repository struct { 32 | UserRepository *UserRepository 33 | db *gorm.DB 34 | } 35 | 36 | // Initialize the postgres database. 37 | func Initialize(c DBConfig) *Repository { 38 | db, err := gorm.Open("postgres", c.connectionInfo()) 39 | if err != nil { 40 | panic(err) 41 | } 42 | 43 | return &Repository{ 44 | UserRepository: newUserRepository(db), 45 | db: db, 46 | } 47 | } 48 | 49 | // AutoMigrate will attempt to automatically migrate all tables 50 | func (r *Repository) AutoMigrate() error { 51 | err := r.db.AutoMigrate(&ginexamples.User{}).Error 52 | if err != nil { 53 | return err 54 | } 55 | return nil 56 | } 57 | -------------------------------------------------------------------------------- /examples/gin_examples/user.go: -------------------------------------------------------------------------------- 1 | package ginexamples 2 | 3 | import ( 4 | "github.com/jinzhu/gorm" 5 | ) 6 | 7 | type User struct { 8 | gorm.Model 9 | Name string 10 | Email string `gorm:"not null;unique_index"` 11 | Password string `gorm:"-"` 12 | PasswordHash string `gorm:"not null"` 13 | SessionID string `gorm:"not null"` 14 | } 15 | 16 | type UserRepository interface { 17 | Store(user *User) error 18 | Update(user *User) error 19 | Find(id string) (*User, error) 20 | FindByEmail(email string) (*User, error) 21 | FindBySessionID(sessionID string) (*User, error) 22 | } 23 | 24 | type UserService interface { 25 | CreateUser(u *User, password string) (*User, error) 26 | GetUser(id string) (*User, error) 27 | UserAuthenticationProvider 28 | } 29 | 30 | type UserAuthenticationProvider interface { 31 | Login(email string, password string) (*User, error) 32 | Logout(sessionID string) error 33 | CheckAuthentication(sessionID string) (*User, error) 34 | } 35 | -------------------------------------------------------------------------------- /gen_contributors.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | result=`curl -s 'https://api.github.com/repos/talkgo/nit/contributors' | jq '.[].login' | sed -e 's/"//g'` 4 | 5 | for element in $result 6 | do 7 | if [ `grep -c $element CONTRIBUTORS` -eq '0' ]; then 8 | echo 'add contributors.' 9 | echo $element >> CONTRIBUTORS 10 | echo $element 11 | all-contributors add $element code 12 | fi 13 | done 14 | 15 | all-contributors check 16 | 17 | echo 'add contributors completed.' 18 | echo 'contributors generate...' 19 | all-contributors generate 20 | echo 'contributors generate completed.' 21 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/talkgo/night 2 | 3 | go 1.19 4 | 5 | require github.com/smartystreets/goconvey v1.6.4 6 | 7 | require ( 8 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect 9 | github.com/jtolds/gls v4.20.0+incompatible // indirect 10 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect 11 | ) 12 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= 2 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 3 | github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= 4 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 5 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= 6 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= 7 | github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= 8 | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 9 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 10 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 11 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 12 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 13 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 14 | -------------------------------------------------------------------------------- /layouts/_default/index.json: -------------------------------------------------------------------------------- 1 | {{- $.Scratch.Add "index" slice -}} 2 | {{- range where .Site.Pages "Type" "not in" (slice "json") -}} 3 | {{- $.Scratch.Add "index" (dict "location" .Permalink "title" .Title "text" .Plain) -}} 4 | {{- end -}} 5 | {{- $.Scratch.Get "index" | jsonify -}} -------------------------------------------------------------------------------- /layouts/shortcodes/badges.html: -------------------------------------------------------------------------------- 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 |
{{ .Get "title" }}
3 |{{ printf "%s" .Inner | markdownify }}
4 |{{ .Get "title" }}
3 |{{ printf "%s" .Inner | markdownify }}
4 |