每日新闻

每日新闻

GoCN每日新闻资讯
有问必答

有问必答

Go相关的问题,技术相关的问题
文章分享

文章分享

技术文章分享,让知识传播给更多的人
招聘应聘

招聘应聘

为Gopher服务的招聘应聘平台

钛核互动急招Go服务器工程师的职位-想做游戏的看过来

招聘应聘lisa_zhao 回复了问题 • 3 人关注 • 2 个回复 • 2053 次浏览 • 2016-10-27 17:40 • 来自相关话题

根据dockerfile docker build 遇到的错误

有问必答zradelaide1122 回复了问题 • 2 人关注 • 2 个回复 • 3962 次浏览 • 2016-10-27 14:59 • 来自相关话题

stdin 和命令行(例如:-dir some/path/to/dir ) 是一回事吗

有问必答stevewang 回复了问题 • 2 人关注 • 1 个回复 • 1666 次浏览 • 2016-10-27 14:14 • 来自相关话题

如何看待golang(1.9?)新的GC 的Proposal?

有问必答niugou 回复了问题 • 14 人关注 • 6 个回复 • 6607 次浏览 • 2016-10-27 13:15 • 来自相关话题

go如何调用exe并捕获输出?

有问必答philosophia14 回复了问题 • 2 人关注 • 2 个回复 • 3888 次浏览 • 2016-10-27 13:13 • 来自相关话题

Docker与Golang的巧妙结合

文章分享田浩浩 发表了文章 • 0 个评论 • 3210 次浏览 • 2016-10-27 11:48 • 来自相关话题

**译文转载:[Docker与Golang的巧妙结合](http://dockone.io/article/1712)** --- 【编者的话】这是一个展示在使用Go语言时如何让Docker更有用的提示与技巧 ...查看全部
**译文转载:[Docker与Golang的巧妙结合](http://dockone.io/article/1712)**

---

【编者的话】这是一个展示在使用Go语言时如何让Docker更有用的提示与技巧的简辑。例如,如何使用不同版本的Go工具链来编译Go代码,如何交叉编译到不同的平台(并且测试结果!),或者如何制作真正小的容器镜像。

下面的文章假定你已经安装了Docker。不必是最新版本(这篇文章不会使用Docker任何花哨的功能)。

## 没有go的Go
*...意思是:“不用安装`go`就能使用Go”*

如果你写Go代码,或者你对Go语言有一点点兴趣,你肯定要安装了Go编译器和Go工具链,所以你可能想知道:“重点是什么?”;但有些情况下,你想不安装`Go`就来编译Go。

* 机器上依旧有老版本Go 1.2(你不能或不想更新),不得不使用这个代码库,需要一个高版本的工具链。
* 想使用Go1.5的交叉编译功能(例如,确保能从一个Linux系统创建操作系统X的二进制文件)。
* 想拥有多版本的Go,但不想完全弄乱系统。
* 想100%确定项目和它所有的依赖,下载,建立和运行在一个纯净的系统上。

如果遇到上述情况,找Docker来解决!

### 在容器里编译一个程序

当你安装了Go,你可以执行`go get -v github.com/user/repo`来下载,创建和安装一个库。(`-v`只是信息显示,如果你喜欢工具链快速和静默地运行,可以将它移除!)

你也可以执行`go get github.com/user/repo/...`来下载,创建和安装那个repo(包括库和二进制文件)里面所有的东西。

我们可以在一个容器里面这样做!

试试这个:
```
docker run golang go get -v github.com/golang/example/hello/...
```

这将拉取golang镜像(除非你已经有了,那它会马上启动),并且创建一个基于它的容器。在那个容器里,go会下载一个“hello world”的例子,创建它,安装它。但它会把它安装到这个容器里……我们现在怎么运行那个程序呢?

###在容器里运行程序
一个办法是提交我们刚刚创建的容器,即,打包它到一个新的镜像:
```
docker commit $(docker ps -lq) awesomeness
```

注意:`docker ps –lq`输出最后一个执行的容器的ID(只有ID!)。如果你是机器的唯一用户,并且你从上一个命令开始没有创建另一个容器,那这个容器就是你刚刚创建的“hello world”的例子。

现在,可以用刚刚构建的镜像创建容器来运行程序:
```
docker run awesomeness hello
```

输出会是`Hello, Go examples!`。

### 闪光点
当用`docker commit`构建镜像时,可以用`--change`标识指定任意[Dockerfile](https://docs.docker.com/engine/reference/builder/)命令。例如,可以使用一个`CMD`或者`ENTRYPOINT`命令以便`docker run awesomeness`自动执行hello。

###在一次性容器上运行
如果不想创建额外的镜像只想运行这个Go程序呢?

使用:
```
docker run --rm golang sh -c \
"go get github.com/golang/example/hello/... && exec hello"
```

等等,那些花哨的东西是什么?

* `--rm` 告诉Docker CLI一旦容器退出,就自动发起一个`docker rm`命令。那样,不会留下任何东西。
* 使用shell逻辑运算符`&&`把创建步骤(`go get`)和执行步骤(`exec hello`)联接在一起。如果不喜欢shell,`&&`意思是“与”。它允许第一部分`go get...`,并且如果(而且仅仅是如果!)那部分运行成功,它将执行第二部分(`exec hello`)。如果你想知道为什么这样:它像一个懒惰的`and`计算器,只有当左边的值是`true`才计算右边的。
* 传递命令到`sh –c`,因为如果是简单的做`docker run golang "go get ... && hello"`,Docker将试着执行名为`go SPACE get SPACE etc`的程序。并且那不会起作用。因此,我们启动一个shell,并让shell执行命令序列。
* 使用`exec hello`而不是`hello`:这将使用hello程序替代当前的进程(我们刚才启动的shell)。这确保`hello`在容器里是PID 1。而不是shell的是PID 1而`hello`作为一个子进程。这对这个微小的例子毫无用处,但是当运行更有用的程序,这将允许它们正确地接收外部信号,因为外部信号是发送给容器里的PID 1。你可能会想,什么信号啊?好的例子是`docker stop`,发送`SIGTERM`给容器的PID 1。

###使用不同版本的Go
当使用`golang`镜像,Docker扩展为`golang:latest,`将(像你所猜的)映射到Docker Hub上的最新可用版本。

如果想用一个特定的Go版本,很容易:在镜像名字后面用那个版本做标签指定它。

例如,想用Go 1.5,修改上面的例子,用`golang:1.5`替换`golang`:
```
docker run --rm golang:1.5 sh -c \
"go get github.com/golang/example/hello/... && exec hello"
```

你能在Docker Hub的[Golang镜像页面](https://hub.docker.com/r/library/golang/tags/)上看到所有可用的版本(和变量)。

###在系统上安装
好了,如果想在系统上运行编译好的程序,而不是一个容器呢?我们将复制这个编译了的二进制文件到容器外面。注意,仅当容器架构和主机架构匹配的时候,才会起作用;换言之,如果在Linux上运行Docker。(我排除的可能是运行Windows容器的人!)

最容易在容器外获得二进制文件的方法是映射`$GOPATH/bin`目录到一个本地目录,在`golang`容器里,`$GOPATH`是`/go.`所以我们可以如下操作:
```
docker run -v /tmp/bin:/go/bin \
golang go get github.com/golang/example/hello/...
/tmp/bin/hello
```

如果在Linux上,将看到`Hello, Go examples!`消息。但如果是,例如在Mac上,可能会看到:
```
-bash:
/tmp/test/hello: cannot execute binary file
```

我们又能做什么呢?

###交叉编译
Go 1.5具备[优秀的开箱即用交叉编译能力](http://dave.cheney.net/2015/08/22/cross-compilation-with-go-1-5),所以如果你的容器操作系统和/或架构和你的系统不匹配,根本不是问题!

开启交叉编译,需要设置`GOOS`和/或`GOARCH`。

例如,假设在64位的Mac上:
```
docker run -e GOOS=darwin -e GOARCH=amd64 -v /tmp/crosstest:/go/bin \
golang go get github.com/golang/example/hello/...
```

交叉编译的输出不是直接在`$GOPATH/bin`,而是在`$GOPATH/bin/$GOOS_$GOARCH.`。换言之,想运行程序,得执行`/tmp/crosstest/darwin_amd64/hello.`。

###直接安装到$PATH
如果在Linux上,甚至可以直接安装到系统bin目录:
```
docker run -v /usr/local/bin:/go/bin \
golang get github.com/golang/example/hello/...
```

然而,在Mac上,尝试用`/usr`作为一个卷将不能挂载Mac的文件系统到容器。会挂载Moby VM(小Linux VM藏在工具栏Docker图标的后面)的`/usr`目录。(译注:目前Docker for Mac版本可以自定义设置挂载路径)

但可以使用`/tmp`或者在你的home目录下的什么其它目录,然后从这里复制。
## 创建依赖镜像
我们用这种技术产生的Go二进制文件是静态链接的。这意味着所有需要运行的代码包括所有依赖都被嵌入了。动态链接的程序与之相反,不包含一些基本的库(像“libc”)并且使用系统范围的复制,是在运行时确定的。

这意味着可以在容器里放弃Go编译好的程序,没有别的,并且它会运行。

我们试试!

###scratch镜像
Docker生态系统有一个特殊的镜像:`scratch.`这是一个空镜像。它不需要被创建或者下载,因为定义的就是空的。

给新的Go依赖镜像创建一个新的空目录。

在这个新目录,创建下面的Dockerfile:
```
FROM scratch
COPY ./hello /hello
ENTRYPOINT ["/hello"]
```

这意味着:*从scratch开始(一个空镜像),*增加`hello`文件到镜像的根目录,*定义`hello`程序为启动这个容器后默认运行的程序。

然后,产生`hello`二进制文件如下:
```
docker run -v $(pwd):/go/bin --rm \
golang go get github.com/golang/example/hello/...
```

**注意**:不需要设置`GOOS`和`GOARCH`,正因为,想要一个运行在Docker容器里的二进制文件,不是在主机上。所以不用设置这些变量!

然后,创建镜像:
```
docker build -t hello .
```

测试它:
```
docker run hello
```

(将显示“Hello, Go examples!”)

最后但不重要,检查镜像的大小:
```
docker images hello
```

如果一切做得正确,这个镜像大约2M。相当好!

###构建东西而不推送到Github
当然,如果不得不推送到GitHub,每次编译都会浪费很多时间。

想在一个代码段上工作并在容器中创建它时,可以在`golang`容器里挂载一个本地目录到`/go`。所以`$GOPATH`是持久调用:`docker run -v $HOME/go:/go golang ....`

但也可以挂载本地目录到特定的路径上,来“重载”一些包(那些在本地编辑的)。这是一个完整的例子:
```
# Adapt the two following environment variables if you are not running on a Mac
export GOOS=darwin GOARCH=amd64
mkdir go-and-docker-is-love
cd go-and-docker-is-love
git clone git://github.com/golang/example
cat example/hello/hello.go
sed -i .bak s/olleH/eyB/ example/hello/hello.go
docker run --rm \
-v $(pwd)/example:/go/src/github.com/golang/example \
-v $(pwd):/go/bin/${GOOS}_${GOARCH} \
-e GOOS -e GOARCH \
golang go get github.com/golang/example/hello/...
./hello
# Should display "Bye, Go examples!"
```

## 网络包和CGo的特殊情况
进入真实的Go代码世界前,必须承认的是:在二进制文件上有一点点偏差。如果在使用CGo,或如果在使用`net`包,Go链接器将生成一个动态库。这种情况下,`net`包(里面确实有许多有用的Go程序!),罪魁祸首是DNS解析。大多数系统都有一个花哨的,模块化的名称解析系统(像名称服务切换),它依赖于插件,技术上,是动态库。默认地,Go将尝试使用它;这样,它将产生动态库。

我们怎么解决?

###重用另一个版本的libc
一个解决方法是用一个基础镜像,有那些程序功能所必需的库。几乎任何“正规”基于GNU libc的Linux发行版都能做到。所以,例如,使用`FROM debian`或`FROM fedora`,替代`FROM scratch`。现在结果镜像会比原来大一些;但至少,大出来的这一点将和系统里其它镜像共享。

注意:这种情况不能使用Alpine,因为Alpine是使用musl库而不是GNU libc。

###使用自己的libc
另一个解决方案是像做手术般地提取需要的文件,用`COPY`替换容器里的。结果容器会小。然而,这个提取过程困难又繁琐,太多更深的细节要处理。

如果想自己看,看看前面提到的`ldd`和名称服务切换插件。

###用netgo生成静态二进制文件
我们也可以指示Go不用系统的libc,用本地DNS解析代替Go的`netgo`。

要使用它,只需在`go get`选项加入`-tags netgo -installsuffix netgo`。

* `-tags netgo`指示工具链使用`netgo`。
* `-installsuffix netgo`确保结果库(任何)被一个不同的,非默认的目录所替代。如果做多重`go get`(或`go build`)调用,这将避免代码创建和用不用netgo之间的冲突。如果像目前我们讲到的这样,在容器里创建,是完全没有必要的。因为这个容器里面永远没有其他Go代码要编译。但它是个好主意,习惯它,或至少知道这个标识存在。

## SSL证书的特殊情况
还有一件事,你会担心,你的代码必须验证SSL证书;例如,通过HTTPS联接外部API。这种情况,需要将根证书也放入容器里,因为Go不会捆绑它们到二进制文件里。

###安装SSL证书
再次,有很多可用的选择,但最简单的是使用一个已经存在的发布里面的包。

Alpine是一个好的选择,因为它非常小。下面的`Dockerfile`将给你一个小的基础镜像,但捆绑了一个过期的跟证书:
```
FROM alpine:3.4
RUN apk add --no-cache ca-certificates apache2-utils
```

来看看吧,结果镜像只有6MB!

注意:`--no-cache`选项告诉`apk`(Alpine包管理器)从Alpine的镜像发布上获取可用包的列表,不保存在磁盘上。你可能会看到Dockerfiles做这样的事`apt-get update && apt-get install ... && rm -rf /var/cache/apt/*`;这实现了(即在最终镜像中不保留包缓存)与一个单一标志相当的东西。

一个附加的回报:把你的应用程序放入基于Alpine镜像的容器,让你获得了一堆有用的工具。如果需要,现在你可以吧shell放入容器并在它运行时做点什么。

## 打包
我们看到Docker如何帮助我们在干净独立的环境里编译Go代码;如何使用不同版本的Go工具链;以及如何在不同的操作系统和平台之间交叉编译。

我们还看到Go如何帮我们给Docker创建小的,容器依赖镜像,并且描述了一些静态库和网络依赖相关的微妙联系(没别的意思)。

除了Go是真的适合Docker项目这个事实,我们希望展示给你的是,Go和Docker如何相互借鉴并且一起工作得很好!

###致谢
这最初是在2016年GopherCon骇客日提出的。

我要感谢所有的校对材料、提出建议和意见让它更好的人,包括但不局限于:

- [Aaron Lehmann](https://github.com/aaronlehmann)
- [Stephen Day](https://twitter.com/stevvooe)
- [AJ Bowen](https://twitter.com/s0ulshake)

所有的错误和拼写错误都是我自己的;所有的好东西都是他们的!

**原文链接:[Docker + Golang = <3](https://blog.docker.com/2016/09/docker-golang/)(翻译:[陈晏娥](http://dockone.io/people/cyeaaa) 审校:[田浩浩](http://dockone.io/people/llitfkitfk))**

Golang 文件路径问题

回复

有问必答abaddon 发起了问题 • 1 人关注 • 0 个回复 • 3057 次浏览 • 2016-10-27 10:34 • 来自相关话题

Go会缓存DNS吗?

有问必答astaxie 回复了问题 • 5 人关注 • 5 个回复 • 4030 次浏览 • 2016-10-26 20:57 • 来自相关话题

用户名登录不了网站

回复

站点反馈hmly 发起了问题 • 1 人关注 • 0 个回复 • 2243 次浏览 • 2016-10-26 18:18 • 来自相关话题

GoCN第二期《老司机带你看Go风景》——数据库达人陈非

文章分享hmly 回复了问题 • 13 人关注 • 13 个回复 • 20687 次浏览 • 2016-10-26 18:16 • 来自相关话题

好玩的github项目-NES - Go 语言开发的任天堂游戏模拟器

Go开源项目wwdyy 发表了文章 • 3 个评论 • 1862 次浏览 • 2016-10-26 15:17 • 来自相关话题

这是一个完全用 Go 语言开发的 NES 红白机模拟器,该项目使用 OpenGL 和 GLFW 处理视频,PortAudio 处理音频。这是一个完全用 Go 语言开发的 NES 红白机模拟器,该项目使用 OpenGL 和 GLFW 处理视频,PortAudio ...查看全部
这是一个完全用 Go 语言开发的 NES 红白机模拟器,该项目使用 OpenGL 和 GLFW 处理视频,PortAudio 处理音频。这是一个完全用 Go 语言开发的 NES 红白机模拟器,该项目使用 OpenGL 和 GLFW 处理视频,PortAudio 处理音频。

github主页:https://github.com/fogleman/nes

![](http://static.oschina.net/uploads/img/201505/28074047_0VAU.gif)

![](https://camo.githubusercontent.com/b79b1e9e61e8bf05eb4e42f137b87efba5e1d9af/687474703a2f2f692e696d6775722e636f6d2f70776574424c762e706e67)

「滴滴运维」招聘——诚求运维架构师

招聘应聘laiwei 发表了文章 • 2 个评论 • 2210 次浏览 • 2016-10-26 14:43 • 来自相关话题

滴滴作为国内最大的一站式出行平台,每天承担着千万级用户的出行需求。滴滴运维团队,承担着7x24小时保障公司业务安全、稳定、高效的运行的重任,为用户提供高质量的在线服务,并持续提升整个公司的运维效率。 ### 岗位职责 - ...查看全部
滴滴作为国内最大的一站式出行平台,每天承担着千万级用户的出行需求。滴滴运维团队,承担着7x24小时保障公司业务安全、稳定、高效的运行的重任,为用户提供高质量的在线服务,并持续提升整个公司的运维效率。

### 岗位职责
- 负责滴滴线上业务的日常运维、优化、容量管理等工作,7x24小时保障线上业务的稳定运行
- 负责维护公司运维基础设施的正常运行
- 负责公司运维基础设施开发,包括监控系统,运维平台,自动化部署系统,弹性云平台
- 研究运维新技术和方向,持续提高生产力

### 职位要求
- 有较大规模在线业务运维、优化等工作经验
- 熟悉Linux操作系统,计算机网络等,基础知识扎实
- Linux系统下熟练使用C、golang或Python、Ruby、Shell等脚本语言开发
- 学习能力强,肯钻研,认真踏实
- 有良好的时间观念,能很好的沟通交流,乐于分享

###加分项
- 重度github用户加分
- 有golang项目开发经验加分
- 阅读过OpenFalcon源码的加分
- 是Go中国社区活跃成员的加分



------------

在这里,我们一起来接受挑战,改变现状。我们坚持运维标准化、产品化、开源的理念,让每个公司都能享受到最好的运维产品。


------------

简历,请直投 laiwei@didichuxing.com 或者 加我微信 hellolaiwei

go实现抓妹子图片

文章分享wwdyy 发表了文章 • 4 个评论 • 1573 次浏览 • 2016-10-26 14:09 • 来自相关话题

转自csdn,作者:vspeter -------------------- ```go import ( "bytes" "fmt" "io/ioutil" "net/htt ...查看全部
转自csdn,作者:vspeter
--------------------
```go
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"os"
"regexp"
"strconv"
)

const (
PATH string = "~/meizi" //文件存储路径
STARTURL string = "http://www.mzitu.com/model" //妹子图模块列表页url
CONCURRENCY int = 3 //并发下载数
)

var (
c1 chan string //通道:负责STARTURL,以后可以做成从命令参数里读取哦
c2 chan string //通道: 负责传输所有的模块url
c3 chan []string //通道:负责传输imgUrl
c4 chan int //通道: 负责传输每张图片的下载完成状态
c5 chan int //通道:负责传输当前下载数
)

func init() {
c1 = make(chan string, 1)
c2 = make(chan string, 100)
c3 = make(chan []string, 1000)
c4 = make(chan int, 3)
c5 = make(chan int, 10)
go CgetList()
go Cdownload()
}
func main() {
c1 <- STARTURL
go CgetModel()
num := 0
for count := range c5 {
num = num + count
fmt.Println("已下载:", num)
}
}

//调度器, 拉取所有模块
func CgetModel() {
modelPage := getPage(<-c1)
for i := 1; i <= modelPage; i++ {
modelUrl := STARTURL + "/page/" + strconv.Itoa(i)
c2 <- modelUrl
}
}

//调度器拉取所有图片url,这里其实还可以多分一层
func CgetList() {
k := 0
tmp := make([]string, 3)
for modelUrl := range c2 {
imgLists := getList(modelUrl)
for _, imgList := range imgLists {
imgPage := getPage(imgList)
for j := 1; j <= imgPage; j++ {
imgUrl := imgList + "/" + strconv.Itoa(j)
if k < CONCURRENCY {
tmp[k] = imgUrl
k++
} else {
c3 <- tmp
k = 0
}
}
}
if k != 0 {
c3 <- tmp
k = 0
}
}

}

//调度器, 下载图片
func Cdownload() {
for imgUrls := range c3 {
if len(imgUrls) > 0 {
for _, imgUrl := range imgUrls {
go func() {
download(imgUrl)
c4 <- 1
}()
}
num := 0
for k := range c4 {
num = num + k
if num == len(imgUrls) {
c5 <- num
break
}
}
}
}
}

//图片列表
func getList(url string) (l []string) {
reg, _ := regexp.Compile(`

.*?

`)
_, html, _ := getHtml(url)
lists := reg.FindAllStringSubmatch(html, 1000)
for _, list := range lists {
l = append(l, list[1])
}
return
}

//下载html
func getHtml(url string) (error, string, error) {
response, err := http.Get(url)
defer response.Body.Close()
html, err1 := ioutil.ReadAll(response.Body)
return err, string(html), err1
}

//获取最大分页
func getPage(url string) (page int) {
_, html, _ := getHtml(url)
reg, _ := regexp.Compile(`(\d*)`)
s := reg.FindAllStringSubmatch(html, 200)
if len(s) < 2 {
fmt.Println("获取失败")
os.Exit(-1)
}
page, _ = strconv.Atoi(s[len(s)-1][1])
return

}

//下载图片
func download(url string) {
reg, _ := regexp.Compile(`

(.*?)

`)
reg1, _ := regexp.Compile(`http:\/\/pic\.dofay\.com/(.*)`)
_, html, _ := getHtml(url)
iterms := reg.FindAllStringSubmatch(html, 100)
for _, iterm := range iterms {
imgUrl := iterm[1]
imgPath := reg1.FindAllStringSubmatch(imgUrl, 100)
imgPaths := bytes.Split([]byte(imgPath[0][1]), []byte("/"))
path := PATH + "/" // + iterm[2]
imgResponse, _ := http.Get(imgUrl)
defer imgResponse.Body.Close()
imgByte, _ := ioutil.ReadAll(imgResponse.Body)
pInfo, pErr := os.Stat(path)
if pErr != nil || pInfo.IsDir() == false {
errDir := os.Mkdir(path, os.ModePerm)
if errDir != nil {
fmt.Println(errDir)
os.Exit(-1)
}
}
fn := path + "/" + string(imgPaths[len(imgPaths)-1])
_, fErr := os.Stat(fn)
var fh *os.File
if fErr != nil {
fh, _ = os.Create(fn)
} else {
fh, _ = os.Open(fn)
}
defer fh.Close()
fh.Write(imgByte)
}
}
```

ModuleAB:基于beego框架开发的阿里云备份/归档解决方案

Go开源项目Xiphin 发表了文章 • 3 个评论 • 2592 次浏览 • 2016-10-26 11:50 • 来自相关话题

![](http://static.oschina.net/uploads/space/2016/0701/111442_JPya_727443.png) ModuleAB 第一个正式版本发布了,ModuleAB 是阿里云备份/归档解 ...查看全部
![](http://static.oschina.net/uploads/space/2016/0701/111442_JPya_727443.png)

ModuleAB 第一个正式版本发布了,ModuleAB 是阿里云备份/归档解决方案。


作者介绍:

> TonyChyi
- github: https://github.com/tonychee7000
- email: tonychee1989@gmail.com
- blog: https://tonychyi.wetofu.top

项目托管:

> - 服务端:
https://github.com/ProjectModuleAngelaBaby/ProjectModuleAB_Server
- 客户端:
https://github.com/ProjectModuleAngelaBaby/ProjectModuleAB_Agent

环境要求:

> 1. bower >= 1.7.6
2. go >= 1.6
3. beego framework >= 1.6.1
4. redis >= 3.0.0
5. mysql >= 5.6

服务端构建:

```bash
mkdir -p project/src
cd project/src
git clone --recursive https://github.com/ProjectModuleAngelaBaby/ProjectModuleAB_Server moduleab_server
cd moduleab_server
go get -v
go get github.com/beego/bee
export PATH="$GOPATH/bin:$PATH"
make # you will get 'moduleab_agent.tar.gz'

```

客户端构建:

```bash
mkdir -p project/src
cd project/src
git clone --recursive https://github.com/ProjectModuleAngelaBaby/ProjectModuleAB_Agent moduleab_agent
cd moduleab_agent
go get -v
make # you will get 'moduleab_agent.tar.gz'
```

> **PS**: Then use the moduleab_server.tar.gz and moduleab_agent.tar.gz to deploy anywhere you want.(然后用moduleab_server.tar.gz、moduleab_agent.tar.gz部署到任何你想要的位置。)

服务端配置:

```
appname = moduleab_server
httpport = 7001
# run mode has following options:
# dev: development mode
# deb: debug mode, log will be HUGE!
# initdb: create data in database, DONT USE if you already have data in database.
# proc: production mode.
runmode = dev
autorender = false
copyrequestbody = true
EnableDocs = false

EnableAdmin = false
AdminHttpAddr = "localhost"
AdminHttpPort = 8088

sessionon = true

loginkey = 61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o

logFile = "logs/moduleab_server.log"
pidFile = "logs/moduleab_server.pid"

[database]
mysqluser = "ModulesAB"
mysqlpass = "ModulesAB"
mysqlurl = "127.0.0.1:3306"
mysqldb = "ModuleAB"
mysqlprefex = ""

[aliapi]
apikey= "TestAbcd" # Ali api key
secret="TestAAA" # Ali api secret
oasport=80
oasusessl=false

[redis]
host = "127.0.0.1:6379"
password = ""
key = "ModuleAB"

[websocket]
timeout=10
pingperiod=5

# policyrun use cron-like syntax: "s m h dom mon dow"
[misc]
checkoasjobperiod=10
policyrun="0 * * * * 1"
```

客户端配置:

```
server=http://localhost:7001
# you need to set this with the conf on server.
loginkey=guess?
# loglevel might be
# debug, info, warn, error, fatal
loglevel=debug
uploadthreads=5
pidfile=moduleab.pid
```

本次改动如下:

> 1. 客户端(Agent)的运行状态可以在服务端显示了
2. 所有的可执行文件实现守护进程,自动运行于后台
3. 客户端新增低内存模式,可运行于内存小于 1G 的机器
4. 修复不能自动释放 TCP 连接的问题
5. 修复当上传的文件带有后缀空格时引发阿里云 OSS 错误

问题反馈:

> https://github.com/ProjectModuleAngelaBaby/ProjectModuleAB_Server/issues

如果我有决定权, Golang...

技术讨论goofansu 回复了问题 • 11 人关注 • 12 个回复 • 2965 次浏览 • 2016-10-26 11:24 • 来自相关话题