Go modules

§Definition

A module is a collection of related go packages. Modules are the unit of source code interchange and versionning.

§Quick history

  • Go before 1.5: populating GOPATH with go get.
  • Go 1.5 and after: dependency vendoring is introduced.
  • vgo is proposed as a prototype for Go modules support.
  • Go 1.11 (beta): vgo is being merged and refined as go mod (experimental).

§Terminology

This article refers to recurrent expressions. Let’s clarify them:

  • “Module root”: the directory containing the file named go.mod.
  • “Module path”: the import path prefix corresponding to the module root.
  • “Main module”: the module containing the directory where the go command is run.

§Module structure

A module is a tree of Go source files to which is added a file named go.mod. It contains the module import name, and the declaration of dependency requirements, exclusions and replacements. Its content would look like this:

module my/thing
  
require (
        one/thing v1.3.2
        other/thing v2.5.0 // indirect
        ...
)

exclude (
        bad/thing v0.7.3
)

replace (
        src/thing 1.0.2 => dst/thing v1.1.0
)

Guide: gorilla/mux

The name mux stands for “HTTP request multiplexer”. Like the standard http.ServeMux, mux.Router matches incoming requests against a list of registered routes and calls a handler for the route that matches the URL or other conditions. The main features are:

* Requests can be matched based on URL host, path, path prefix, schemes,
  header and query values, HTTP methods or using custom matchers.
* URL hosts, paths and query values can have variables with an optional
  regular expression.
* Registered URLs can be built, or "reversed", which helps maintaining
  references to resources.
* Routes can be used as subrouters: nested routes are only tested if the
  parent route matches. This is useful to define groups of routes that
  share common conditions like a host, a path prefix or other repeated
  attributes. As a bonus, this optimizes request matching.
* It implements the http.Handler interface so it is compatible with the
  standard http.ServeMux.

Let’s start registering a couple of URL paths and handlers:

func main() {
  r := mux.NewRouter()
  r.HandleFunc("/", HomeHandler)
  r.HandleFunc("/products", ProductsHandler)
  r.HandleFunc("/articles", ArticlesHandler)
  http.Handle("/", r)
  log.Fatal(http.ListenAndServe(":12345", nil))
}

Docker: 对Docker Remote API进行认证

  • 建立证书授权中心
$ sudo mkdir /etc/docker
$ cd /etc/docker
$ echo 01 | sudo tee ca.csl
$ sudo openssl genrsa -des3 -out ca-key.pem
$ sudo openssl req -new -x509 -days 365 -key ca-key.pem -out ca.pem
  • 创建服务器的证书签名请求和密钥
$ sudo openssl genrsa -des3 -out server-key.pem
$ sudo openssl req -new -key server-key.pem -out server.csr
$ sudo openssl x509 -req -days 365 -in server.csr -CA ca.pem -CAkey ca-key.pem -out server-cert.pem
$ sudo openssl rsa -in server-key.pem -out server-key.pem
$ sudo chmod 0600 /etc/docker/server-key.pem /etc/docker/server-cert.pem /etc/docker/ca-key.pem /etc/docker/ca.pem
  • 配置Docker守护进程 (/etc/docker/daemon.json on Linux systems, or C:\ProgramData\docker\config\daemon.json on Windows.)
{
  "debug": true,
  "tls": true,
  "tlscacert": "/etc/docker/ca.pem",
  "tlscert": "/etc/docker/server-cert.pem",
  "tlskey": "/etc/docker/server-key.pem",
  "hosts": ["tcp://<config of CN>:2376"]
}

Gogs: PR-5322

Add new Dockerfile.docker-ce for docker-ce(>=v17.06) to build Gogs’s docker image

Docker-CE can be given to a new build stage by adding AS name to the FROM instruction sine release version of v17.06. The Dockerfile’s FROM instruction like below:

FROM

FROM <image> [AS <name>]

Or

FROM <image>[:<tag>] [AS <name>]

Or

FROM <image>[@<digest>] [AS <name>]
  • Optionally a name can be given to a new build stage by adding AS name to the FROM instruction. The name can be used in subsequent FROM and COPY --from=<name|index> instructions to refer to the image built in this stage.

Find Docker-ce official document here.

Gogs: PR-5262

Fix make build failure when enviroment of GOPATH have multiple items

[alimy@rover gogs]$ pwd
/home/alimy/art/arg/src/github.com/gogs/gogs
[alimy@rover gogs]$ echo $GOPATH
/home/alimy/art/ago:/home/alimy/art/arg
[alimy@rover gogs]$ make
go install "-v" -ldflags '-X "github.com/gogs/gogs/pkg/setting.BuildTime=2018-06-04 06:17:19 UTC" -X "github.com/gogs/gogs/pkg/setting.BuildGitHash=c08aab90ec696b7fcc56b8da0a468e74d266b89e"' -tags '""'
cp '/home/alimy/art/ago:/home/alimy/art/arg/bin/gogs' .
cp: cannot stat '/home/alimy/art/ago:/home/alimy/art/arg/bin/gogs': No such file or directory
Makefile:36: recipe for target 'build' failed
make: *** [build] Error 1

In this scene GOPATH have two item (/home/alimy/art/ago and /home/alimy/art/arg) and gogs source is not in first GOPATH items, when excecute go install ... will install to path that contain the source of gogs’s GOPATH items. when cp gogs file back will occur error like above. this patch fixed this problem.

[alimy@rover gogs]$ echo $GOPATH
/home/alimy/art/ago:/home/alimy/art/arg
[alimy@rover gogs]$ pwd
/home/alimy/art/arg/src/github.com/gogs/gogs
[alimy@rover gogs]$ echo ${PWD%%src*}
/home/alimy/art/arg/

NewSQL: 分布式数据库TiDB、CockroachDB

TiDB

TiDB 开源分布式 NewSQL 关系型数据库 TiDB 是新一代开源分布式 NewSQL 数据库,模型受 Google Spanner / F1 论文的启发,实现了自动的水平伸缩,强一致性的分布式事务,基于 Raft 算法的多副本复制等重要 NewSQL 特性。TiDB 结合了 RDBMS 和 NoSQL 的优点,部署简单,在线弹性扩容和异步表结构变更不影响业务, 真正的异地多活及自动故障恢复保障数据安全,同时兼容 MySQL 协议,使迁移使用成本降到极低。

CockroachDB (蟑螂DB/小强DB)

CockroachDB(中文名蟑螂DB,所以又可以称为小强DB),是构建于事务处理及强一致性KV存储上的分布式SQL数据库,支持水平扩展、自动容错处理、强一致性事务,并且提供SQL接口用于数据处理,是Google Spanner/F1的开源实现。 CockroachDB适用于应用对数据要求精确、可靠、完全正确的场景,支持自动复制、均匀分布、基于极小配置的数据恢复,可用于分布式的、可复制的联机事务处理(OLTP),多数据中心的部署,私有云的基础构建,它不适用于读少写多的场景,可以用内存数据库来代替,也不适用于复杂的join查询,重量级的数据分析及联机分析处理(OLAP)。

Logus:另一种简单、优雅、高效打Log的方式

起源:

最近项目中有使用Uber的zap(Go语言生态中一种高效打印Log的实用库,久经考验)打印log,用的顺手,于是借鉴其中的设计思想,在Android环境下封装Log类提供相似功能。

设计思想:

分离消息与数据域,避免字符串拼接和效率低的字符串格式化

  • 把log信息分两段:消息和数据域;消息是必须的, 数据域是个数可变的键-值对
  • 消息仅仅是String,不带任何格式化或字符串拼接
  • 数据域是以key-value的形式成对作为参数传给打印函数,忽略最后一个不成对参数
  • 内部实现是使用StringBuilder组合最终要打印的信息,避免过多的字符串拼接导致log打印频繁时给gc过多压力
  • StackTrace信息是可以设置打印或不打印

用例:

// file: MainActivity.java
@Override
protected void onResume() {
    super.onResume();
    Logus.d("just a message");
    Logus.e("a field message", "a", 1);
    Logus.w("3 fields but see 2", "a", 1, "b", true, "c");
    Logus.V("Main", "with prefix just a message");
    Logus.E("Main", "with prefix 2 fields", "a", 10, "b", false);
    Logus.E("Main", "with prefix 3 fields but log 2", "a", 10, "b", true, "c");
    Logus.setStackTrace(false);
    Logus.E("Main", "no stack trace with prefix");
}

// 输出:
04-19 22:12:56.209 3256-3256/net.gility.note  D/Logus: MainActivity.java(425)#onResume > just a message
04-19 22:12:56.210 3256-3256/net.gility.note  E/Logus: MainActivity.java(426)#onResume > a field message { a=1; }
04-19 22:12:56.210 3256-3256/net.gility.note  W/Logus: MainActivity.java(427)#onResume > 3 fields but see 2 { a=1; b=true; }
04-19 22:12:56.211 3256-3256/net.gility.note  V/Logus: MainActivity.java(428)#onResume Main> with prefix just a message
04-19 22:12:56.212 3256-3256/net.gility.note  E/Logus: MainActivity.java(429)#onResume Main> with prefix 2 fields { a=10; b=false; }
04-19 22:12:56.213 3256-3256/net.gility.note  E/Logus: MainActivity.java(430)#onResume Main> with prefix 3 fields but log 2 { a=10; b=true; }
04-19 22:12:56.213 3256-3256/net.gility.note  D/Logus: > no stack trace no prefix
04-19 22:12:56.213 3256-3256/net.gility.note  E/Logus: Main> no stack trace with prefix