Go和Angular的Web应用开发~直到Angular的展示~

首先

用Go和Angular创建Web应用程序。
由于是第一次尝试,所以发布将分几次进行。
此外,在使用Go进行Web应用程序开发时,我认为应该考虑使用已经存在的框架,如gin或gorilla,但同时也可以将其作为学习的机会进行自主开发。

    • Github

 

    https://github.com/ponta-dev/angular-go

希望

这次我们将使用Go的Web服务器来显示通过ng new创建的Angular项目的初始显示页面,而不是使用ng serve。

构建环境

Angular CLI: 8.0.1
Go 版本:go1.12.5 windows/amd64

假设Node.js已经安装。
使用Go的模块模式,将项目创建在GOPATH以外的其他位置。

git init //適当なディレクトリで
go mod init github.com/ponta-dev/angular-go

根据需要创建.gitignore等文件。项目层次结构如下所设想。

root
|-server //GOのサーバ側実装(github.com/ponta-dev/angular-go/serverパッケージ)
|-template //Angularのビルド結果のjsやindex.htmlが出力される場所
|-ui //Angularのプロジェクト
go.mod
.gitignore

创建Angular项目

ng new ui
cd ui //以下起動確認
ng serve --open

确认Go的构建
在server/main目录下创建一个main.go和main_test.go文件
内容只需要用fmt.Println(“hello world”)之类的执行确认就可以了

go run ./server/main/main.go //GOの実行確認
go test -v github.com/ponta-dev/angular-go/server/main //テストの実行確認

这是可以在同一个目录中确认Go和Angular运行的位置。

构建设置

更改Angular的配置
想要更改的配置有以下两个:
1. 更改构建结果的输出路径
2. 设置基本URL

以下是中文翻译:
1. 第一个问题是,在使用ng build构建时,输出目标路径默认情况下位于Angular项目内,但对于Go来说略微不舒服,所以需要将输出目标更改为项目根目录下的template目录。
2. 第二个问题是,为了将http://localhost:8080/angular-go作为主页URL对GO的Web服务器进行设置,需要进行基本URL(/angular-go/)的配置。

        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "../template", //出力先の変更
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.scss"
            ],
            "scripts": [],
            "baseHref": "/angular-go/" //ベースURLの設定
          },

在进行ng build和ng serve之前,需要进行基本的URL设置。要注意的是,如果baseHref设置为”angular-go”之类的值,可能无法正确设置(应设置为”/angular-go/”)。

Go语言的实现

使用Go的Web服务器通过net/http包进行实现。 对于特定URL的HTTP请求,注册处理程序并执行某些服务器处理操作。 在这种情况下,对于主页URL的请求,可以返回输出到template目录的index.html。

如果实现了http.Handler接口并且实现了ServeHTTP(ResponseWriter, *Request)函数,那么它就是一个合适的处理程序。

type Handler interface {
        ServeHTTP(ResponseWriter, *Request)
}

当在HandleServeHTTP函数中实现以下内容时,可以返回index.html文件。

//index.htmlテンプレートの取得
index := template.Must(template.ParseFiles(HTMLTemplatePath + "/" + IndexHTML)) // "template/index.html"

//index.htmlの書き込み
if err := index.Execute(w, nil); err != nil {
    log.Fatal("index.html Write Error", err)
}

template.Must是html/template包中返回*template.Template的方法的包装器函数。当尝试获取index.html时发生错误时(例如路径错误),它会引发恐慌。

通过将上述处理程序注册到主页URL,可以创建一个Go Web服务器,它将返回使用Angular创建的index.html。

资源访问

虽然可以返回index.html,但是这样做无法在http://localhost:8080/angular-go上显示Angular的用户界面。这是因为无法获取index.html引用的资源文件,例如~~.js和~~.ico。因此,需要允许Go的Web服务器访问这些资源。
然而,资源文件的访问URL是/angular-go/~~.js之类的,因此当前情况下会触发与/angular-go/主页URL相关的处理程序。
即使对所有资源访问都注册处理程序也不太合理,因此需要找到一种巧妙的方法来解决这个问题。
关于这个问题可能有几种解决方案,在我搜索的结果中,出现了以下文章。

    • Getting Started With Angular and Go :

 

    • https://medium.com/@anshap1719/getting-started-with-angular-and-go-setting-up-a-boilerplate-project-8c273b81aa6

AngularのプロジェクトをビルドしてGolangで動かす:

这次笔者打算用一种与上述方法不同的方式来允许资源访问。
请谅解实现可能不够完美或存在不应该使用的实现的可能性。

首先,所有对资源文件的访问都将在主页URL的处理程序中进行处理。使用Go的regexp包的正则表达式来检查请求的路径,以将资源文件(如.js文件)和对主页URL的访问分开。对于对主页URL的访问,将在上述处理程序中返回index.html;而对于对资源文件的访问,则将其作为文件服务器返回相应的资源文件。使用regexp进行正则表达式判定的示例如下所示。

//constで下記のような定数を定義し
ResourceRegexp = `.*\.js$|.*\.ico$|.*\.js\.map$`

// *regexp.Regexp構造体の取得
ResourceRegexp := regexp.MustCompile(ResourceRegexp)
if ResourceRegexp.MatchString(r.URL.Path) {
 // リソースファイルに対する処理
}else {
 // index.htmlの返却
}

在Go中,文件服务器可通过http.FileServer进行更好的实现。
由于它应该禁止对指定目录以外的访问,所以从安全性的角度来看是推荐的。
http.FileServer的返回值是http.Handler接口的实现,因此只需执行ServeHTTP函数就可以执行文件服务器的处理程序。

// http.StripPrefixでベースURL(/angular-go/を除外する
// http.FileServer(http.Dir(HTMLTemplatePath))でファイルサーバのハンドラを取得
fileServer := http.StripPrefix(HomePrefix, http.FileServer(http.Dir(HTMLTemplatePath)))

// ServeHTTP
// 自前のServeHTTPの引数のリクエストとレスポンスをそのまま受け渡す
if ResourceRegexp.MatchString(r.URL.Path) {
    //FileServerのServeHTTPをキック
    fileServer.ServeHTTP(w, r)
} 
WS000000.JPG

下一次计划

这次我介绍了如何在Go的Web应用程序中显示Angular的Hello World。
下次计划介绍以下内容之一。

    • PostgreSQLとGoサーバーの通信

 

    GoサーバをRestのWebAPI化