go谚语
本文摘自 https://www.kancloud.cn/cserli/golang/524388
本文译自go-proverbs, 脱胎于 Rob Pike 振奋人心的演讲视频 talk at Gopherfest SV 2015 (bilibili).
不要通过共享内存进行通信, 通过通信共享内存 (Don’t communicate by sharing memory, share memory by communicating)
本文摘自 https://www.kancloud.cn/cserli/golang/524388
本文译自go-proverbs, 脱胎于 Rob Pike 振奋人心的演讲视频 talk at Gopherfest SV 2015 (bilibili).
不要通过共享内存进行通信, 通过通信共享内存 (Don’t communicate by sharing memory, share memory by communicating)
epoll原理
参考:https://my.oschina.net/editorial-story/blog/3052308
嵌套
在go文件中使用,最简单直观的动态库 .so 或 dll
的形式,最安全但是很不爽也比较慢的[TOC]
大多数人认为我们格式化Go代码gofmt 以使代码看起来更好或结束团队成员之间关于程序布局的争论。但是, 1是,如果一个算法定义围棋源代码是如何被格式化,然后编程,如goimports 或 gorename 或者 go fix,可以更容易地编辑源代码,而无需编写代码回来时引入伪格式更改。这有助于您长期维护代码。
我认为源代码格式化工具非常简洁 提供。解析器/ ast /漂亮也是一件好事 打印机可用作mod。
但是,我不确定是否尝试强制执行格式化样式 拒绝配置格式化程序的能力(如FAQ提及) 是个好主意。至少go /打印机包可能是好的 即使命令行gofmt工具,也允许更灵活的配置 没有。 对于gofmt的输出,没有人或将永远不会满意, 但它实际上相当不错,更重要的是,人们适应 令人惊讶的是,这种风格起初看起来很陌生。特别 在格式化方面,风格实际上只是“你习惯的”。 由于Go是一种全新的语言,所以不应该这样 很难习惯不同的格式。
我们希望人们能够准确地接受gofmt的输出 因为它结束了这种风格的辩论。怎么样 C有很多不同的支撑款式吗?太多。
就个人而言,我发现让gofmt格式化为我是一种解放, 因为这意味着我有更多可用的神经元 攻击有趣的编程问题。有 我不喜欢gofmt输出的东西,但我不喜欢 不再担心他们了。
但所有这些都错过了我认为最激动人心的事情 关于gofmt:事实上我们有一个可以拿起每个人的工具 Go树中的源文件,将其解析为内部表示, 然后将完全相同的字节放回原位。 (很大一部分 这是由于进入gofmt的工作量,以及 其余的是因为我们同意对gofmt进行标准化 一旦你拥有了这样一个工具,它变得非常容易 在中间插入机械处理,解析之间 和印刷。所以我们拥有一个程序的所有难点 操纵工具只是坐着等待使用。我已经开始了 以前为C编写类似的工具,从来没有得到过输出 完全匹配输入。同意接受“gofmt风格” 是在有限数量的代码中使它可行的部分。
我希望人们会按照自己的代码使用gofmt。 正如我所说,它不需要超过几个星期 习惯于新的编码风格,特别是如果你是一个品牌 新语言,每个人都有巨大的利益 相同的风格。
我们当然打算继续格式化所有代码 使用gofmt去树。像Go一样,这是一个实验。
Russ
[TOC]
这段时间搞到了bilibili的一部分源码,那个事件你知道的,就不说了。怀着对大牛的向往,打算研究一下,之前听说主程做的这个架构很牛逼,就算是代码泄露也不会对服务器造成影响,而且模块化做的非常好,小弟们码好代码,主程一键做个合并打包发布就行。自动化做的很好。就想知道到底是怎么做的,于是我了解到了他——Bazel。
原文链接 https://filipnikolovski.com/managing-go-monorepo-with-bazel/
在InPlayer中,我们有一个使用
微服务架构风格构建的平台,它基本上将应用程序构建为许多不同服务的集合。在这篇文章中,我将讨论如何建构(structure),构建(build)和部署(deploy)Go应用程序。
我们编写的每一段Go代码都驻留在一个Git存储库中 - 一个monorepo。由于每个库和服务都在一个项目中,因此它允许我们进行交叉更改,而无需使用某些外部包管理工具。基本上,代码不可能不同步,我们所做的每个更改都可以视为一个单元。
虽然好处很明显,但使用Go monorepo的挑战是如何有效地构建和测试每个包。答案 - Bazel。
Bazel是一款速度极快的构建工具。它只重建必要的东西,它利用高级缓存机制和并行执行,使您的构建非常,非常快。除了这些功能外,它还可以管理您的代码依赖项,调用外部工具和插件,还可以从二进制可执行文件构建Docker镜像。它使用go build
引擎盖,但它也可以支持许多不同的语言,而不仅仅是Go。您可以将它用于Java,C ++,Android,iOS和各种其他语言平台。您可以在三个主要操作系统上运行Bazel - Windows,macOS和Linux。
在我们深入了解Bazel之前,首先让我们讨论一下我们的项目结构:
platform
|-- src
| |-- foo
| | |--cmd
| | | `--bar
| | | |--BUILD
| | | `--main.go
| | `--pkg
| |-- utils
| |-- vendor
| |-- Gopkg.lock
| |-- Gopkg.toml
| |-- BUILD
| `-- WORKSPACE
|-- README.md
`-- gitlab-ci.yml
该platform
目录是我们的根本,一切从这里开始。在该文件夹中,我们有CI配置和src
保存所有代码的目录。每个服务都是src
文件夹中的子目录,在每个服务中我们都有两个顶级目录,即cmd
和pkg
文件夹。在下面cmd
我们有我们的二进制文件(我们的主程序)的pkg
目录,该目录用于我们的服务库。
Bazel从名为
的目录中组织的代码构建软件,该目录基本上是我们的src目录。在这里,我们的工作空间目录必须包含一个名为的文件WORKSPACE
,该文件可能引用了构建输出所需的外部依赖关系以及构建规则。
这是一个示例WORKSPACE文件:
http_archive(
name = "io_bazel_rules_go",
url = "https://github.com/bazelbuild/rules_go/releases/download/0.9.0/rules_go-0.9.0.tar.gz",
sha256 = "4d8d6244320dd751590f9100cf39fd7a4b75cd901e1f3ffdfd6f048328883695",
)
http_archive(
name = "bazel_gazelle",
url = "https://github.com/bazelbuild/bazel-gazelle/releases/download/0.9/bazel-gazelle-0.9.tar.gz",
sha256 = "0103991d994db55b3b5d7b06336f8ae355739635e0c2379dea16b8213ea5a223",
)
git_repository(
name = "io_bazel_rules_docker",
remote = "https://github.com/bazelbuild/rules_docker.git",
tag = "v0.3.0",
)
load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")
go_rules_dependencies()
go_register_toolchains()
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
gazelle_dependencies()
load(
"@io_bazel_rules_docker//go:image.bzl",
_go_image_repos = "repositories",
)
_go_image_repos()
在此文件中,有几个依赖项添加到工作区。我们特别声明我们将使用rules_go和rules_docker依赖项以及Gazelle,这将帮助我们生成Bazel所需的一些文件。不要担心,如果您不熟悉这种语法,需要一些时间来适应它。
Bazel有一个关于
包的概念,它被定义为相关文件的集合以及它们之间依赖关系的规范。如果Bazel工作空间内的目录包含名为的文件BUILD
,则会将该目录视为包。包中包含其目录中的所有文件,以及其下的所有子目录,除了那些本身包含BUILD文件的文件。
BUILD文件包含构建规则,这些规则定义了我们应该如何构建包。您可以在此处阅读有关概念和术语的更多信息。
在开始一个新项目时,我们需要做的第一件事是在根目录中添加一个BUILD文件,这将加载稍后用于运行Gazelle with Bazel 的瞪羚规则。
package(default_visibility = ["//visibility:public"])
load("@io_bazel_rules_docker//container:container.bzl")
load("@io_bazel_rules_go//go:def.bzl", "go_prefix", "gazelle")
go_prefix("github.com/example/project")
gazelle(
prefix = "github.com/example/project/src",
name = "gazelle",
command = "fix",
external = "vendored"
)
添加此文件后,我们可以使用以下命令运行Gazelle:
bazel run //:gazelle
这将根据项目中的go文件生成新的BUILD文件。稍后添加新程序和库时,应使用相同的命令更新现有的BUILD文件,否则构建可能会失败。
作为一个例子(基于我们之前显示的项目结构),gazelle将为我们的bar
程序生成一个BUILD文件,该文件位于foo
包中,如下所示:
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
package(default_visibility = ["//visibility:public"])
go_library(
name = "go_default_library",
srcs = ["main.go"],
importpath = "github.com/example/project/src/foo/cmd/bar",
visibility = ["//visibility:private"],
deps = [
#Any dependencies that our library has will be loaded here
],
)
go_binary(
name = "bar",
embed = [":go_default_library"],
importpath = "github.com/example/project/src/foo/cmd/bar",
visibility = ["//visibility:public"],
)
现在通过运行命令bazel build //foo/...
bazel将构建我们的Go程序并将二进制文件保存在输出目录中。如果要构建整个项目,只需bazel build //...
在根文件夹中运行即可。
如果您为您的库和程序(您应该)编写测试,gazelle将为go_test
它们生成规则,然后您可以运行bazel test //...
将运行所有测试。
Bazel的高级缓存,使运行build
和test
命令对整个工作区超级快,因为它只会建造或测试您已更改的文件,以及依赖于这些修改过的文件的文件。
⚠️注意:确保将CI服务器设置为缓存输出目录,否则运行bazel不会带来太多好处。
在我们想要将二进制文件构建和部署为docker图像的情况下,bazel有一套很好的规则可以做到这一点。更为重要的是,Bazel并不需要Docker拉取,构建或推送镜像。这意味着您可以使用这些规则在Windows / OSX上构建Docker镜像而无需使用docker-machine
或者boot2docker
也不需要在笔记本电脑上进行
访问。
我们bar
程序的BUILD文件的完整示例如下所示:
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
# First we load the go_image and container_push rules
load("@io_bazel_rules_docker//go:image.bzl", "go_image")
package(default_visibility = ["//visibility:public"])
go_library(
name = "go_default_library",
srcs = ["main.go"],
importpath = "github.com/example/project/src/foo/cmd/bar",
visibility = ["//visibility:private"],
deps = [
#Any dependencies that our library has will be loaded here
],
)
go_binary(
name = "bar",
embed = [":go_default_library"],
importpath = "github.com/example/project/src/foo/cmd/bar",
visibility = ["//visibility:public"],
)
go_image(
name = "docker",
binary = ":bar",
)
该go_image
规则使用distroless镜像作为基础,只添加二进制文件作为要运行的命令。container_push
如果要将映像推送到远程存储库,也可以使用该规则。
要将二进制文件作为docker镜像运行,只需键入bazel run //foo/cmd/bar:docker
命令即可。您还可以构建一个tar包,然后可以使用以下命令手动将其加载到docker中:
bazel build //foo/cmd/bar:docker.tar
docker load -i bazel-output/foo/cmd/bar/docker.tar
您可以在此处找到有关规则的更多信息。