Microsoft Docs「Go でサーバーレス アプリを構築する」の補足情報

# はじめに

Microsoft Docsの「[Go でサーバーレス アプリを構築する](https://docs.microsoft.com/ja-jp/learn/modules/serverless-go/)」を使ってGo入門ハンズオンを開催しようとしているのですが、誤植があったり情報が足りなかったりと、このまま使用するのは難しいため、補足情報を用意しました。

動作確認はmacOSで行いましたが、WindowsとLinuxでも大丈夫なように記述しています。

ローカル環境で動作させる分には、2021年11月以降の各製品のバージョンに対応できています。

- [Azure Functions 4.0 and .NET 6 support are now generally available - Microsoft Tech Community](https://techcommunity.microsoft.com/t5/apps-on-azure-blog/azure-functions-4-0-and-net-6-support-are-now-generally/ba-p/2933245)

# 補足情報

## [はじめに](https://docs.microsoft.com/ja-jp/learn/modules/serverless-go/1-introduction)

補足情報はありません。

## [カスタム ハンドラー](https://docs.microsoft.com/ja-jp/learn/modules/serverless-go/2-custom-handlers)

補足情報はありません。

## [Web アプリ](https://docs.microsoft.com/ja-jp/learn/modules/serverless-go/3-web-api)

### REST API を Go で構築する

#### ・ライブラリをインポートする。

ソースコードにて、各ライブラリーの最後のカンマを削除。

誤：

```Go
import (
   "fmt",
   "log",
   "net/http"
)
```

正：

```Go
import (
   "fmt"
   "log"
   "net/http"
)
```

#### ・要求を管理する。 

ソースコードにて、文章に合わせて関数名を「handleRoute」に、第1引数の型のパッケージとインターフェースの区切り文字をコロンからカンマに、第２引数を参照型（型の前に*を付ける）に、それぞれ修正。引数と型を区切っていたコロンを削除。

誤：

```Go
func handleRequest(w: http:ResponseWriter, r: http.Request) {
```

正：

```Go
func handleRoute(w http.ResponseWriter, r *http.Request) {
```

### Azure Functions アプリを作成する

#### ・Visual Studio Code をインストールする

公式サイトからダウンロードしてインストールします。

- [Download Visual Studio Code - Mac, Linux, Windows](https://code.visualstudio.com/download)

#### ・Azure Functions 用の Visual Studio Code 拡張機能をインストールする。

Visual Studio Codeを使ってインストールします。

1. Visual Studio Codeを起動。
1. 画面左側のアイコン列から「Extentions」（四角が４つ）アイコンをクリック。
1. 「Search Extentions in Marketplace」欄に「Azure Functions」と入力して、欄下に一覧表示された「Azure Functions」の「Install」をクリック。

#### ・Azure Functions Core Tools をインストールする。 

2021年11月にAzure Functionsのバージョン 4 が正式リリースになりました。

Azure/azure-functions-core-tools サイトから「v4」をインストールします。

- [GitHub - Azure/azure-functions-core-tools: Command line tools for Azure Functions](https://github.com/Azure/azure-functions-core-tools#installing)

macOSの場合、インストールに `brew` コマンドが必要となります。

- [The Missing Package Manager for macOS (or Linux) — Homebrew](https://brew.sh/)

### Visual Studio Code を使用して Functions アプリをスキャフォールディングする

プロジェクト生成後のファイルが異なっている。（proxies.json ファイルはない）

誤：

- `host.json`
- `local.setting.json`
- `proxies.json`
- `function.json`

正：

- `host.json`
- `local.setting.json`
- `function.json`

### プロジェクトを構成する

#### ・既定の実行可能パスを構成する。

.json ファイル名が間違っている。

誤：

`プロジェクト ルートの function.json ファイルを探します。`

正：

`プロジェクト ルートの host.json ファイルを探します。`

## [演習 - カスタム ハンドラーを使用してアプリを構築する](https://docs.microsoft.com/ja-jp/learn/modules/serverless-go/4-exercise-custom-handler)

### アプリをスキャフォールディングする

スキャフォールディング後のファイルが異なっている。（proxies.json ファイルはない）

誤：

```
hello/
  function.json
.funcignore
.gitignore
host.json
local.settings.json
proxies.json
```

正：

```
hello/
  function.json
.funcignore
.gitignore
host.json
local.settings.json
```

### アプリを作成する

#### ２. server.go の内容を次のようにします。

Go 1.16からio/ioutilパッケージの使用が非推奨となったため、新しいコーディングとしてioパッケージに変更。

Go 1.16以前：

```Go
 "io/ioutil"
```

Go 1.17以降：

```Go
 "io"
```

#### ５. import ステートメントと main() 関数の間に、次のコードを追加します。

Go 1.16からio/ioutilパッケージの使用が非推奨となったため、新しいコーディングとしてioパッケージに変更。

Go 1.16以前：

```Go
body, _ := ioutil.ReadAll(r.Body)
```

Go 1.17以降：

```Go
body, _ := io.ReadAll(r.Body)
```

### アプリを実行する

Visual Studio Code で server.go ファイルを開いている時、ターミナル上で server.go ファイルを書き換えると、Visual Studio Code の server.go ファイルの１行目の「package main」に波下線が表示される。進めていくには問題ないが、以下の対応を行うことで解消できます。

#### １. の前に追加

ターミナル にて、プロジェクト ルートのひとつ上の階層に移動して ```go mod init [プロジェクト名]``` を実行して、プロジェクト ルートに戻ります。

次の例では、プロジェクト ルートは「```/Users/luigi/af01```」、ひとつ上の階層は「```/Users/luigi```」、プロジェクト名は「```af01```」です。

```zsh
% pwd
/Users/luigi/af01

% cd ..

% pwd
/Users/luigi

% go mod init af01 
go: creating new go.mod: module af01
go: to add module requirements and sums:
	go mod tidy

% cd ad01

% pwd
/Users/luigi/af01
```

ターミナル にて、プロジェクト ルートで `go fmt server.go` を実行すると、

```zsh
% go fmt server.go
```

ソースコードが自動整形されます。その結果は Visual Studio Code で開いている server.go ファイルに即反映されます。

#### ２. と ３. の間に追加

`extensionBundle` 要素を削除します。

```json
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[2.*, 3.0.0)"
  },
```

## [キュー トリガー](https://docs.microsoft.com/ja-jp/learn/modules/serverless-go/5-queue)

### ローカルでの開発

#### ２. エミュレーター機能を使用するには、コマンド パレットで ... を選択して開始します。

機能名の誤りを修正。（Azure → Azurite）

誤：

`[Azure: Start Queue Service](Azure: キュー サービスの開始)`

正：

`[Azurite: Start Queue Service](Azurite: キュー サービスの開始)`

## [演習 - キュー メッセージを処理する](https://docs.microsoft.com/ja-jp/learn/modules/serverless-go/6-exercise-queue)

### 注意

#### Azurite 拡張機能をダウンロード

Visual Studio Codeを使ってインストールします。

1. Visual Studio Codeを起動。
1. 画面左側のアイコン列から「Extentions」（四角が４つ）アイコンをクリック。
1. 「Search Extentions in Marketplace」欄に「Azurite」と入力して、欄下に一覧表示された「Azurite」の「Install」をクリック。


私の場合、Azurite 機能拡張では上手くいかなかったため、Azurite CLIをインストールしました。

- [参考URL] [ローカルでの Azure Storage の開発に Azurite エミュレーターを使用する | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/storage/common/storage-use-azurite?tabs=npm#install-azurite)

Azurite インストールには、Node.jsが必要になりますので、まだの場合はインストールします。

- [Download | Node.js](https://nodejs.org/en/download/)

ターミナルで、`npm install -g azurite` コマンドを実行します。

```zsh
% npm install -g azurite
```

#### Azure Storage Explorerをダウンロード

製品サイトからダウンロードしてインストールします。

- [Azure Storage Explorer – クラウド ストレージ管理 | Microsoft Azure](https://azure.microsoft.com/ja-jp/features/storage-explorer/)

#### Azure Functions Core Tools をダウンロード

Azure Functions Core Tools は、前回の演習でインストール済み。

キューを含めた拡張機能バンドルをインストールします。Goはネイティブ サポート外のため、手動でインストールします。

- [参考URL] [Azure Functions バインド拡張機能を登録する | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-bindings-register#access-extensions-in-non-net-languages)

ターミナルで、.NET SDK のバージョンが 3.1 以上であることを確認します。

```zsh
% dotnet --list-sdks
```

.NET SDK がインストールされていない場合、公式サイトから最新バージョンをダウンロードします。

- [.NET Downloads (Linux, macOS, and Windows)](https://dotnet.microsoft.com/en-us/download/dotnet)

[参考] 古いバージョンのSDKを削除する場合

- [.NET ランタイムと SDK を削除する | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/core/install/remove-runtime-sdk-versions)

プロジェクト ルートの host.json ファイルから、`extensionBundle` 要素を削除します。

```json
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[2.*, 3.0.0)"
  },
```

ターミナルで、プロジェクト ルートから `func extensions install` コマンドを実行します。

```zsh
% func extensions install
```

### アプリをスキャフォールディングする

#### ８. ルートで、server.go という名前のファイルを作成します。 

プロジェクト生成後のファイルが異なっている。（proxies.json ファイルはない）

誤：

```
queueTrigger/
  function.json
.funcignore
.gitignore
host.json
local.settings.json
proxies.json
server.go
```

正：

```
queueTrigger/
  function.json
.funcignore
.gitignore
host.json
local.settings.json
server.go
```

### アプリを作成する

#### １. server.go ファイルを開き、次のコードを追加します。

encoding/jsonパッケージの最後のカンマを、未使用のためio/ioutilパッケージを、それぞれ削除。（残したままだと `go build` でエラーになる）

誤：

```Go
  "encoding/json",
  "fmt"
  "io/ioutil"
```

正：

```Go
  "encoding/json"
  "fmt"
```

#### ３. queueHandler() メソッドを見つけ、次のように更新します。

受信する変数の名前を型を修正。

誤：

```Go
  var reqData map[string]interface{}
  json.Unmarshal(invokeRequest.Data["queueItem"], &reqData)
```

正：

```Go
  var parsedMessage string
  json.Unmarshal(invokeRequest.Data["queueItem"], &parsedMessage)
```

### アプリを実行する

### １. の前に追加

Azurite 機能拡張からの実行で上手く動作しない場合、ターミナルで、Azurite のキューサービスを実行します。

```zsh
% azurite --queueHost 127.0.0.1
```

# さいごに

途中だったり、実際にハンズオンを行なうなどして、気付きがあった際には随時修正して行きます。