我刚开始使用Go(golang),并希望为将使用Gradle构建并部署到Docker镜像的项目设置新的项目文件夹结构。我很难确定这个项目结构的样子,主要是因为GOPATH结构以及Go语言工具似乎与使用Gradle或配置可克隆的项目(Git)相对立的事实。
该项目最终将包含用Go编写的各种服务器端代码,用HTML和JavaScript编写的客户端代码,因此我需要一个适合Gradle构建和打包所有这些类型的项目结构。
是否有人为此提供了良好的工作结构和工具建议?
答案 0 :(得分:3)
当我开始使用Go时,我摆弄了各种各样的构建工具,从maven到gulp。
事实证明,至少对我来说,他们弊大于利,所以我开始使用Go看起来不那么惹人注目,但是经过深思熟虑的功能。其中一个是go generate
。添加简单的shell脚本或偶尔使用Makefile进行自动化。
我已经整理了一个示例项目,以使其更加清晰
/Users/you/go/src/bitbucket.org/you/hello/
├── Dockerfile
├── Makefile
├── _templates
│ └── main.html
└── main.go
这是一个简单的网络服务器,服务于“Hello,World!”使用优秀的go.rice工具嵌入到二进制文件中的模板:
//go:generate rice embed-go
package main
import (
"html/template"
"log"
"net/http"
rice "github.com/GeertJohan/go.rice"
)
func main() {
templateBox, err := rice.FindBox("_templates")
if err != nil {
log.Fatal(err)
}
// get file contents as string
templateString, err := templateBox.String("main.html")
if err != nil {
log.Fatal(err)
}
// parse and execute the template
tmplMessage, err := template.New("message").Parse(templateString)
if err != nil {
log.Fatal(err)
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if err := tmplMessage.Execute(w, map[string]string{"Greeting": "Hello, world!"}); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
})
log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}
注意这一行
//go:generate rice embed-go
当您致电go generate
时,将扫描您的源文件以查找此类行,并执行相应的命令。在这种情况下,将生成一个名为rice-embed.go的文件,您的目录将如下所示:
/Users/you/go/src/bitbucket.org/you/hello/
├── Dockerfile
├── Makefile
├── _templates
│ └── main.html
├── main.go
└── rice-box.go
例如,您可以在//go generate
中调用webpack,将您的内容放在一起,然后生成其他内容以从结果中创建rice-box.go
。通过这种方式,您的所有内容都将嵌入到二进制文件中,并且可以轻松部署。
我在这个例子中使用了一个相当简单的Dockerfile:
FROM alpine:latest
MAINTAINER You <you@example.com>
COPY hello /usr/bin
EXPOSE 8080
CMD ["/usr/bin/hello"]
然而,这给我们带来了一个问题:我们无法使用go:generate
来生成docker镜像,因为当我们需要调用go:generate
时,新的二进制文件尚未构建。这会让我们做一些丑陋的事情,比如
go generate && go build && go generate
导致docker图像构建两次以及诸如此类的东西。所以,我们需要一个不同的解决方案
我们当然可以想出类似的东西:
#!/bin/bash
# Checks for existence omitted for brevity
GO=$(which go)
DOCKER=$(which docker)
$GO generate
$GO test
$GO build
$DOCKER -t you/hello .
但是,这会带来一个问题:您将始终使用shell脚本执行整个序列。即使您只想运行测试,也最终会构建docker镜像。随着时间的推移,这加起来。在这种情况下,我倾向于使用
Makefile是GNU make
的配置文件 CC = $(shell which go 2>/dev/null)
DOCKER = $(shell which docker 2>/dev/null)
ifeq ($(CC),)
$(error "go is not in your system PATH")
else
$(info "go found")
endif
ifeq ($(DOCKER),)
$(error "docker not in your system path")
else
$(info "docker found")
endif
.PHONY: clean generate tests docker all
all: clean generate tests hello docker
clean:
$(RM) hello rice-box.go cover.out
generate:
$(CC) generate
tests: generate
$(CC) test -coverprofile=cover.out
hello: tests
$(CC) build
docker: hello
$(DOCKER) build -t sosample/hello .
完整的解释超出了本答案的范围,但您基本上可以做的是,您可以调用make
并构建all
目标:删除旧版本中的文件(clean
),生成新的rice-box.go
(generate
),依此类推。但是,如果您只想运行测试,则调用make test
只会执行目标clean
,generate
和tests
。
答案 1 :(得分:0)
您可以查看我构建项目的方法https://github.com/alehano/gobootstrap 这是一个网络框架。