0

最近发现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/

问题是:

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

    home
    └── mark
        └── code
            ├── go
            │   └── my_revel_app
            ├── php
            │   └── my_php_app
            └── ruby
                └── my_ruby_app
    
  2. 以及如何以正确的方式将它们实际部署在我的远程服务器上?

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

我知道,这可能是一个菜鸟问题,但我在这里看不到逻辑。即使是简单的 Go 程序,我也不需要将它们放入 GOPATH 即可运行。

4

3 回答 3

1

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

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

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

于 2015-12-16T16:12:07.873 回答
1

介绍

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

PHP 和 Go 之间存在一些根本区别,其中之一是 PHP 是一种解释型语言,而 Go 是一种编译型语言。

PHP 是为大多数应用程序设计的,它是一种所谓的解释性语言,这意味着每次调用 PHP 文件时,源代码都会被翻译成机器可读的指令。

另一方面,Go 是一种编译语言,这意味着源代码一次编译为可执行二进制文件并默认静态链接,导致生成的可执行文件没有依赖项(除了为其编译的操作系统),甚至 Go运行。因此,您可以构建一个自给自足的 Web 应用程序,包括 Web 服务器和(使用特殊用途的 Go 包)甚至是图像和样式表等资源文件。

虽然您可以使用go run filename.go它,但它只是go build执行生成的编译二进制文件的快捷方式,如下go run --help所示:

go run [build flags] [-exec xprog] gofiles... [arguments...]

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 服务器。您可以从字面上复制二进制文件并运行它。但是,这并不妨碍您使用更复杂的方法,例如创建软件包,如.debor.rpm或(我更喜欢)Docker 映像。

根据下面的子目录$GOPATH/src:实际上你完全可以自由地在那里组织你的包。然而,三胞胎

codehoster/用户名/包名

是有原因的。该go get命令实际上可以使用 git、Mercurial 和 bzr 站点自动下载包。有关详细信息,请参阅包发布。是的,直接联系这些代码托管站点。go get实际上至少依赖于git 。三元组简单地反映了代码的全局可达位置。当然,您可以将代码存储在 中 $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)
}

但是,我们的 main 函数中仍然有所有处理程序。我们将提取 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 提供一个 Formatter。

$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()))

}

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

于 2015-12-17T17:05:18.797 回答
0

我会一一回答你的问题:

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 是私有的)?

我想第三种方法是命名你的包的最合适的方式,因为导入应该以主机名开头,然后是其余的东西。

于 2017-03-27T16:05:53.083 回答