慕盖茨4494581
介绍我觉得有一些误解。让我们继续努力。PHP 和 Go 之间有一些根本区别,其中之一是 PHP 是一种解释性语言,而不是 Go,Go 是一种编译语言。PHP 被设计并且对于大多数应用程序来说是一种所谓的解释性语言,这意味着每次调用 PHP 文件时,源代码都会被翻译成机器可读的指令。去另一方面是编译型语言,这意味着源代码被编译成可执行的二进制一次和静态连接是默认导致生成的可执行程序有没有依赖关系(比它被编译为OS等),甚至没有去运行。因此,您可以构建一个自给自足的 Web 应用程序,包括 Web 服务器和(使用特殊用途的 Go 包)甚至图像和样式表等资源文件。虽然您可以使用go run filename.go它只是go build执行生成的已编译二进制文件的快捷方式,但正如以下输出所go run --help证明的那样:go run [build flags] [-exec xprog] gofiles... [参数...]Run 编译并运行包含命名的 Go 源文件的主包。Go 源文件被定义为以文字“.go”后缀结尾的文件。默认情况下,'go run' 直接运行编译后的二进制文件:'a.out arguments...'。例子我将向您展示 $GOPATH 及其子目录是如何互连的。让我们以最简单的 Web 服务器示例为例:package main import ( "net/http" "fmt")// Default Request Handlerfunc defaultHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "<h1>Hello %s!</h1>", r.URL.Path[1:])}func main() { http.HandleFunc("/", defaultHandler) http.ListenAndServe(":8080", nil)}我把它放到这样的目录结构中,包括权限和文件大小。这是在 OS X 系统上$GOPATH/src/github.com/mwmahlberg/DemoServer/└── [-rw-r--r-- 178] server_main.go现在,当调用GOOS=linux go build ./...目录 DemoServer 时,在我的情况下,交叉编译二进制文件以在 linux 上运行。二进制文件得到构建,目录如下所示:$GOPATH/src/github.com/mwmahlberg/DemoServer/├── [-rwxr-xr-x 6.2M] DemoServer└── [-rw-r--r-- 178] server_main.go请注意server具有相当大的 6.3M 大小的可执行文件。但是,让我们检查一下:$ file DemoServerserver: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped您实际上可以将此可执行文件复制到任何 64 位 Linux 并通过调用运行它$ ./DemoServer现在,使用http://hostname:8080/Mark调用相应的服务器,您将看到一个网站欢迎您。并不是说这使部署变得非常容易。无需处理任何依赖项,无需配置额外的 Web 服务器。你可以直接复制二进制文件并运行它。但是,这并不妨碍您使用更复杂的方法,例如创建像.deb或.rpm或(我更喜欢)Docker 映像之类的软件包。根据下面的子目录$GOPATH/src:实际上,您可以完全自由地在那里组织您的包。然而,三胞胎代码主机/用户名/包名是有原因的。该go get命令实际上可以使用 git、Mercurial 和 bzr 站点来自动下载包。有关详细信息,请参阅包发布。是的,直接联系那些代码托管站点。该go get实际上是依赖于混帐至少。三元组简单地反映了代码的全局可访问位置。当然,您可以将代码存储在 $GOPATH/src/foobar并将其推送到github.com/mark/foobar,尽管这变得相当不透明,尤其是当我在 github.com 和 bitbucket.org 上的所有其他人托管开放项目时这样做。现在,让我们做一些有用的事情,并在调用日期 url 时显示日期:package main import ( "net/http" "fmt" "time")// Default Request Handlerfunc defaultHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "<h1>Hello %s!</h1>", r.URL.Path[1:])}func dateHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w,"<h1>%s</h1>",time.Now())}func main() { http.HandleFunc("/date",dateHandler) http.HandleFunc("/", defaultHandler) http.ListenAndServe(":8080", nil)}然而,我们的主函数中仍然有所有的处理程序。我们将提取 defaultHandler 和 dateHandler:$GOPATH/src/github.com/mwmahlberg/DemoServer/├── [-rw-r--r-- 214] dateHandler.go├── [-rw-r--r-- 165] defaultHandler.go└── [-rw-r--r-- 178] server_main.go我们server_main.go现在看起来像这样:package main import ( "net/http" )func main() { http.HandleFunc("/date",dateHandler) http.HandleFunc("/", defaultHandler) http.ListenAndServe(":8080", nil)}的defaultHandler.go:package mainimport ( "net/http" "fmt")func defaultHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "<h1>Hello %s!</h1>", r.URL.Path[1:])}还有我们的dateHandler.go:package mainimport ( "net/http" "fmt" "time")func dateHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w,"<h1>%s</h1>",time.Now())}让我们假设我们有一个特定于应用程序的可重用函数,我们想要放入一个包中。为了这个例子,我们将有一个用于 dateHandler 的格式化程序。$GOPATH/src/github.com/mwmahlberg/DemoServer/├── [-rw-r--r-- 214] dateHandler.go├── [-rw-r--r-- 165] defaultHandler.go├── [drwxr-xr-x 102] formatter│ └── [-rw-r--r-- 110] dateformatter.go└── [-rw-r--r-- 178] server_main.go内容dateformatter.go很简单:package formatterimport ( "time")func FormatDate(d time.Time) string { return d.Format(time.RFC850)}我们在我们的日期处理程序中使用它:package mainimport ( "fmt" "net/http" "time" "github.com/mwmahlberg/DemoServer/formatter")func dateHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, formatter.FormatDate(time.Now()))}所以,我希望这会有所帮助。