Wetts's blog

Stay Hungry, Stay Foolish.

0%

用 supervisord ,这样如果服务出错挂掉后,会自动重启

用途之一:为函数定义多个参数

1
2
3
4
// 函数x接受任意数量的int参数
func x(args ...int){

}

用途之二:将切片拆散

1
2
3
// 将切片m(含有3个int型元素)拆散成单个int型作为参数调用函数x
m := make([]int, 3)
x(m...)

转自:http://www.tuicool.com/articles/NjMzIbJ

我们在项目中除了大量的使用Python外,也大量的使用了Golang构建高效基础运行服务。在使用Golang过程中,我们发现Golang程序缺少依赖库版本功能是一个非常令人头大的问题:某些依赖在某个commit之后发生了API变更之后,如果不修改代码很难兼容,然而开发者之间很有可能因为参与的时间不同,导致执行 go get 命令获取的版本不同,而导致在不同电脑上出现编译不通过问题。同时,在多个程序中,如果使用的commit版本不同,也可能会导致程序编译过程中出现不同的问题。

在之前,我们解决这个问题有两个方案,一种是拆解 go get 命令的执行,首先创建对应依赖目录,利用git命令切换至指定的commit,然后执行 go install 命令。另外一种比较省事的方法是使用 godep 工具,这里就不做过多介绍了,具体可以参考文档或者搜索中文教程。

在Golang1.5之后,Go提供了 GO15VENDOREXPERIMENT 环境变量,用于将go build时的应用路径搜索调整成为 当前项目目录/vendor 目录方式。通过这种形式,我们可以实现类似于 godep 方式的项目依赖管理。不过起码在程序编译过程中,再也无需在其他端部署一个 godep 工具。

在使用之前,需要安装一个辅助工具(如果Golang自改一个就好了): go get -u -v github.com/kardianos/govendor

下面,我们用一个例子来说明。首先有一个名为 vendorproj 的项目。假如只有一个文件:

1
2
3
4
5
6
7
8
9
10
11
package main

import (
"github.com/yeeuu/echoic"
)

func main() {
e := echoic.New()
e.SetDebug(true)
e.Run("127.0.0.1:4321")
}

执行一下命令就可以生成vendor文件夹:

1
2
3
4
5
6
$ govendor init
$ ls
main.go vendor
$ cd vendor/
$ ls
vendor.json

这个 vendor.json 会类似 godep 工具中的描述文件版本的功能。接下来,需要执行命令将当前应用必须的文件包含进来

1
$ govendor add +external

如果需要更新或移除,可以参考一下工具的具体文档使用 update 或者 remove 命令即可。这样会在vendor目录下将必须的编译文件移入进来(注意:测试所需依赖并不包含,依赖项目的测试文件也不会包含)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ ls
github.com golang.org vendor.json
$ cat vendor.json
{
"comment": "",
"ignore": "test",
"package": [
{
"path": "github.com/yeeuu/echoic",
"revision": "a7d6994f92e2dc60cff071ae38b204fbd4bd2a3f",
"revisionTime": "2015-12-18T11:14:29+08:00"
},
{
"path": "golang.org/x/net/context",
"revision": "1d9fd3b8333e891c0e7353e1adcfe8a612573033",
"revisionTime": "2015-11-13T15:40:13-08:00"
}
]
}
$ cd github.com/yeeuu/echoic
$ ls
LICENSE context.go group.go router.go
README.md echoic.go response.go

通过设置环境变量 GO15VENDOREXPERIMENT=1 使用vendor文件夹构建文件。可以选择 export GO15VENDOREXPERIMENT=1 或者干脆 GO15VENDOREXPERIMENT=1 go build 执行编译。

通过这种方式就可以保证程序能够实现类似Python中Virtualenv的模式,实现不同程序使用不同版本依赖的目的。

转自:http://studygolang.com/articles/7129

概述

golang的包管理工具有很多,本篇幅主要介绍glide进行包管理。

安装及命令介绍

1
go get github.com/Masterminds/glide
  • glide create|init 初始化项目并创建glide.yaml文件.

  • glide get 获取单个包

    • –all-dependencies 会下载所有关联的依赖包
    • -s 删除所有版本控制,如.git
    • -v 删除嵌套的vendor
  • glide install 安装包

  • glide update|up 更新包

案例测试

准备:本次测试的包是 github.com/mattn/go-adodb ,这个包其中有一个依赖包是 github.com/go-ole/go-ole

下载单个包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
command:
glide get github.com/mattn/go-adodb

glide.lock:
hash: 60061bf3133f0eec2f147f3d80f3e37c402ee12df8cde841b03d80c82a96bab7
updated: 2016-05-18T23:30:08.5219207+08:00
imports:
- name: github.com/mattn/go-adodb
version: 452cccbbcfb7906b3cbc512992557c1083e1011b
devImports: []

glide.yaml:
package: glide_demo6
import:
- package: github.com/mattn/go-adodb

下载单个包, –all-dependencies

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
command:
glide get --all-dependencies -s -v github.com/mattn/go-adodb

glide.lock:
hash: 60061bf3133f0eec2f147f3d80f3e37c402ee12df8cde841b03d80c82a96bab7
updated: 2016-05-18T23:34:48.7545322+08:00
imports:
- name: github.com/go-ole/go-ole
version: 572eabb84c424e76a0d39d31510dd7dfd62f70b2
subpackages:
- oleutil
- name: github.com/gonuts/commander
version: f8ba4e959ca914268227c3ebbd7f6bf0bb35541a
- name: github.com/gonuts/flag
version: 741a6cbd37a30dedc93f817e7de6aaf0ca38a493
- name: github.com/mattn/go-adodb
version: 452cccbbcfb7906b3cbc512992557c1083e1011b
devImports: []

glide.yaml:
package: glide_demo6
import:
- package: github.com/mattn/go-adodb

从lock中可以看到,确实将所有的依赖包都下载了。

下载制定版本号的包

1
2
3
4
5
6
7
8
command:
glide get github.com/go-sql-driver/mysql#v1.2

glide.yaml:
package: glide_demo
import:
- package: github.com/go-sql-driver/mysql
version: v1.2

团队开发

在团队开始时,需要将 glide.yaml 和 glide.lock 进行版本控制,vendor 忽略掉。

模拟下团队开发的流程

A同学:初始化项目,并提交了源码,其中glide.yaml 和 glide.lock的内容如下

1
2
3
4
5
glide.yaml:
package: glide_demo6
import:
- package: github.com/mattn/go-adodb
- package: github.com/go-ole/go-ole
1
2
3
4
5
6
7
8
9
glide.lock:
hash: 18e3b9c2f5c11f3268b22ebdbea09636c5cae28e78f0011578f455c485e9d214
updated: 2016-05-18T23:43:15.8217224+08:00
imports:
- name: github.com/go-ole/go-ole
version: 572eabb84c424e76a0d39d31510dd7dfd62f70b2
- name: github.com/mattn/go-adodb
version: 452cccbbcfb7906b3cbc512992557c1083e1011b
devImports: []

B同学:拉去项目,执行 glide install,会自动下载对应的包

总结

使用glide的好处是,每个项目都采用各自独立的包,而且可以很好的控制包的版本,这在团队开发中尤其重要。

go get 默认会将包安装在 GOPATH 列举的第一个路径中。 你可以使用 go get -u 来更新已经存在的第三方包。

你也可以使用 go get -u all 来更新在你 GOPATH 中的所有第三方包

对于大一点的项目,为不同的项目创建不同的 GOPATH 则更为合理,因为这样更新A项目里的库不会导致B项目出问题。

从go1.5开始,将源码编译成非本地系统的程序,不再需要先生成目的系统的编译工具了,直接加参数编译即可,例如在64位ubuntu上想要编译64位windows的程序,在源码路径下执行

1
GOOS=windows GOARCH=amd64 go build

就结束了(其中GOARCH=amd64可以省略)。当然如果是32位windows,则由于目的系统和本地系统架构不一致需要显示指明,命令变为

1
GOOS=windows GOARCH=386 go build

主要代码结构

consistenthash(提供一致性哈希算法的支持),lru(提供了LRU方式清楚缓存的算法),singleflight(保证了多次相同请求只去获取值一次,减少了资源消耗),还有一些源文件:byteview.go 提供类似于一个数据的容器,http.go提供不同地址间的缓存的沟通的实现,peers.go节点的定义,sinks.go感觉就是一个开辟空间给容器,并和容器交互的一个中间人,groupcache.go整个源码里的大当家,其它人都是为它服务的。

  1. 在jenkins“系统管理”的“管理插件”中安装“Deploy to container Plugin”

  2. 在Jenkins中配置Job,在“构建后操作”中增加“Deploy war/ear to container”

1

参数说明

  • WAR/EAR files

    相对于工作空间的相对路径,也可以写“Ant-style GLOBs”表达式,如:**/*.war,“Ant-style GLOBs”暂时还没有弄明白是什么,经测试可以按如下形式写:source/target/*.warsource/target/yiqifa-adcenter-web.war,建议以“**/*.war”形式填写。

    如本文中使用的Jenkins的工作空间为/data/jenkins,job名称为hyf-test-deploy-plugin,则这里的路径是相对/data/jenkins/hyf-test-deploy-plugin的(其中source是在job中指定的源码存放目录,视设置确定需不需要加上这个目录)

    如果所有配置都正确,在Jenkins的控制台会看到如下图的提示:

    2

    其中“hyf-test-deploy-plugin”为Jenkins的job名称。

  • Context Path

    应用在Tomcat中的部署路径,如上图,部署后可以通过http://172.16.18.192:8080/hyftest来访问部署的应用

  • Manager user name/Manager password

    在“修改Tomcat管理用户配置”中配置好的用户名和密码

  • Tomcat Url

    运程Tomcat的访问路径,如上图中的http://172.16.18.192:8080,插件通过这个地址将应用的war/ear包上传到Tomcat的webapps目录下

  • Add Container

    在这里可以继续增加其他的容器,这样就可以实现将应用同时部署到不同的容器中。

用户名和密码可以到“Tomcat安装目录/conf/tomcat-users.xml”文件中进行查看。

可以看到,默认情况下,Tomcat Manager的用户名和密码是注释掉的,即Tomcat Manager默认是禁用的。

1

General

  • %v 以默认的方式打印变量的值
  • %T 打印变量的类型

Integer

  • %+d 带符号的整型,fmt.Printf(“%+d”, 255)输出+255
  • %q 打印单引号
  • %o 不带零的八进制
  • %#o 带零的八进制
  • %x 小写的十六进制
  • %X 大写的十六进制
  • %#x 带0x的十六进制
  • %U 打印Unicode字符
  • %#U 打印带字符的Unicode
  • %b 打印整型的二进制

Integer width

%5d 表示该整型最大长度是5,下面这段代码

1
2
fmt.Printf("|%5d|", 1)
fmt.Printf("|%5d|", 1234567)

输出结果如下:

1
2
|    1|
|1234567|

%-5d则相反,打印结果会自动左对齐

%05d会在数字前面补零。

Float

  • %f (=%.6f) 6位小数点
  • %e (=%.6e) 6位小数点(科学计数法)
  • %g 用最少的数字来表示
  • %.3g 最多3位数字来表示
  • %.3f 最多3位小数来表示

String

  • %s 正常输出字符串
  • %q 字符串带双引号,字符串中的引号带转义符
  • %#q 字符串带反引号,如果字符串内有反引号,就用双引号代替
  • %x 将字符串转换为小写的16进制格式
  • %X 将字符串转换为大写的16进制格式
  • % x 带空格的16进制格式

String Width (以5做例子)

  • %5s 最小宽度为5
  • %-5s 最小宽度为5(左对齐)
  • %.5s 最大宽度为5
  • %5.7s 最小宽度为5,最大宽度为7
  • %-5.7s 最小宽度为5,最大宽度为7(左对齐)
  • %5.3s 如果宽度大于3,则截断
  • %05s 如果宽度小于5,就会在字符串前面补零

Struct

  • %v 正常打印。比如:{sam {12345 67890}}
  • %+v 带字段名称。比如:{name:sam phone:{mobile:12345 office:67890}
  • %#v 用Go的语法打印。

比如main.People{name:”sam”, phone:main.Phone{mobile:”12345”, office:”67890”}}

Boolean

  • %t 打印true或false

Pointer

  • %p 带0x的指针
  • %#p 不带0x的指针