为了账号安全,请及时绑定邮箱和手机立即绑定

在 Go 中编码的正确方法是什么?

在 Go 中编码的正确方法是什么?

Go
慕码人8056858 2021-11-29 16:31:37
最近发现Revel是一个非常不错的MVC web框架,想试试看。问题是我刚接触 Go,一切似乎都有些不同。使用PHP时,我只是将文件放入/var/www/文件夹,或者使用一些IDE,然后我可以打开浏览器并实时测试它们。使用 RoR 或 Node.js 甚至更容易,我只需转到本地项目文件夹(无论在哪里),在终端中运行一个命令,就可以在localhost:3000.这样,我的本地机器上就有以下结构:home└── mark     └── code         ├── php         │   └── my_php_app         └── ruby             └── my_ruby_app它们都是通过 git 同步的。然后,当我想在我的远程机器上部署时,我只需将它们拉入/var/www/并设置 Apache2/Nginx但是我如何使用 Go 应用程序做到这一点?我在家里的 Linux 机器和 VPS 上都安装了 Go。当我打开~/code/go/mygoapp并尝试使用 运行它时revel run,它说在GOPATH. 所以,我假设,我需要将我所有的 Go 项目与我的其他项目分开,在GOPATH,可以是/usr/local/go/src/或~/gocode/src/。问题是:我应该怎么做,如果我要保持我所有的围棋/狂欢项目go文件夹以及php和ruby本地计算机上那样:home└── mark     └── code         ├── go         │   └── my_revel_app         ├── php         │   └── my_php_app         └── ruby             └── my_ruby_app以及如何以正确的方式将它们实际部署到我的远程服务器上?如果我仍然需要为此使用 GOPATH,我该如何命名包?是GOPATH/src/mygoapp,GOPATH/src/mark/mygoapp还是GOPATH/src/bitbucket.org/mark/mygoapp(虽然这个 repo 是私有的)?我知道,这可能是一个菜鸟问题,但我在这里看不到逻辑。即使使用简单的 Go 程序,我也不需要将它们放到 GOPATH 中才能运行。
查看完整描述

3 回答

?
千万里不及你

TA贡献1784条经验 获得超9个赞

您添加GOPATH包含 go source 的目录(工作区),并符合结构src, pkg, bin。您可以在GOPATH. 在您的系统上相应地定义变量。在GOPATH你的服务器上很可能将是一个比你的本地机器不同。

您可以使用git来共享您的项目。在 github 或 bitbucket 上创建一个帐户,并进行同步。

你的GOPATH点数去工作区。第一个用于存储go get包。


查看完整回答
反对 回复 2021-11-29
?
慕盖茨4494581

TA贡献1850条经验 获得超11个赞

介绍

我觉得有一些误解。让我们继续努力。


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 Handler

func 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 DemoServer

server: 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 Handler

func 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 main


import (

    "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 main


import (

    "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 formatter


import (

    "time"

)


func FormatDate(d time.Time) string {

    return d.Format(time.RFC850)

}

我们在我们的日期处理程序中使用它:


package main


import (

    "fmt"

    "net/http"

    "time"


    "github.com/mwmahlberg/DemoServer/formatter"

)


func dateHandler(w http.ResponseWriter, r *http.Request) {


    fmt.Fprintf(w, formatter.FormatDate(time.Now()))


}

所以,我希望这会有所帮助。


查看完整回答
反对 回复 2021-11-29
?
至尊宝的传说

TA贡献1789条经验 获得超10个赞

我会一一回答你的问题:

1)如果我想将所有 Go/Revel 项目与本地机器上的 php 和 ruby 一起保存在 go 文件夹中,我该怎么办:

其实你不能。Go 提出了一种构建 Go 代码结构的方法,理想情况下应该遵循它。一个工作区由 Go 项目共享,而其他项目则不同,每个项目都有单独的工作区。

2)我如何以正确的方式在我的远程服务器上实际部署它们?

我能想到的一种有效方法是拥有一个单独的构建服务器,在其中构建所有包以及获取远程包(github.com)。Tar 构建的项目。转到您的远程服务器,只需从 bin 运行可执行文件。这节省了在生产服务器上获取和构建远程包的时间。

3) 如果我仍然需要为此使用 GOPATH,我该如何命名包?是 GOPATH/src/mygoapp、GOPATH/src/mark/mygoapp 还是 GOPATH/src/bitbucket.org/mark/mygoapp(虽然这个 repo 是私有的)?

我想第三个将是命名包的最合适的方式,因为导入应该以主机名开头,然后是其余的内容。


查看完整回答
反对 回复 2021-11-29
  • 3 回答
  • 0 关注
  • 187 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信