Step [O1o1o0g1o0] はじめに
いきなり 囲碁プログラム を書くのは大変なので、練習をする
👇 また、技術的でない内容を含むブログを別の場所に 開設する
📖 目指せ!第14回UEC杯コンピューター囲碁大会☆(^q^)<その1>
アーキテクチャ:
What is | This is |
---|---|
OS | Windows |
Editor | Visual Studio Code |
Program Language | Go |
Remote Repository | Git Hub |
Step [O1o1o0g1o1o0] ソースの置き場所(リモート)
👇 まず、ソースの置き場所を決めておく
📖 リポジトリ
Step [O1o1o0g1o2o0] ソースの置き場所(ローカル)
Go言語では ローカルPCのどこにソースを置くかは自分で設定して決めておく。
サンプルでは ユーザーホームの下に置いているので、真似る
👇 以下のコマンドを入力してほしい
Input:
echo %HOMEPATH%
Output:
\Users\むずでょ
ユーザーホームのパスが分かった。この下に go\src
で始まるディレクトリーを作っていく。
私は以下の場所にした
C:\Users\むずでょ\go\src\github.com\muzudho\kifuwarabe-uec14-practice
以降の文章では、あなたのリポジトリに読み替えてほしい
Step [O1o1o0g2o_1o0] Visual Studio Code を使う
がんばって、 Visual Studio Code
を使えるようにしておいてほしい
Step [O1o1o0g2o_1o0] Goエクステンションをインストールする
Visual Studio Code
の Extensions
から、 Go
をインストールしておいてほしい
Step [O1o1o0g2o0] 公式のサンプルプログラムを真似る
👇 とりあえずGo言語の公式のサンプルプログラムを一通りやろう。
Step [O1o1o0g2o1o_1o_10o0] Go言語のインストール
1年ぐらい経つと新しいバージョンが出ていたりするので、Go言語の最新バージョンをダウンロードしておくことにする。
Windows向けには、 .msi
ファイルが配られているので インストールは楽だろう
古いバージョンの Go言語は削除することになる
Go言語のインストール先は C:\Program Files\Go\
とした
Step [O1o1o0g2o1o_1o_11o0] カレントディレクトリー
Visual Studio Code を開く
私の場合、以下のディレクトリーへ移動する
cd C:\Users\むずでょ\go\src\github.com\muzudho\kifuwarabe-uec14-practice
Step [O1o1o0g2o1o_1o0] Go言語のバージョン確認
👇 以下のカレントディレクトリーから、以下のコマンドをコピーして、ターミナルに貼り付けてほしい
👉 📂 kifuwarabe-uec14-practice
Input:
go version
Output:
go version go1.19 windows/amd64
Step [O1o1o0g2o1o_1o0] マルチ ワークスペース
べつに ワークスペースは1つでいいが、
練習で 複数のワークスペースを作れることを示す
👇 以下の3つのディレクトリーを新規作成してほしい
📂 kifuwarabe-uec14-practice
👉 ├── 📂 greetings
👉 │ └── 📂 japanese
👉 └── 📂 web-service-gin
👇 カレントディレクトリーは以下の通りとする
👉 📂 kifuwarabe-uec14-practice
├── 📂 greetings
│ └── 📂 japanese
└── 📂 web-service-gin
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go work init
👇 すると 以下のファイルが自動生成される
📂 kifuwarabe-uec14-practice
├── 📂 greetings
│ └── 📂 japanese
├── 📂 web-service-gin
👉 └── 📄 go.work
go 1.19
この 📄 go.work
ファイルは1個だけ作る。
このファイルが置いてあると Go言語は ワークスペースズ モード
になる
ワークスペースズ モード
になると、
今まで覚えた Go言語の go run .
コマンドが使えなくなったり、
今まで通っていたパッケージへのパスが通らなくなる。
このような制限を解除する方法はあとで説明する
また、せっかく作った 📂 greetings
、 📂 greetings\japanese
、 📂 web-service-gin
だが、
まだ 2番目、3番目、4番目のワークスペース にはできない。あとで説明する
Step [O1o1o0g2o1o_1o0] 設定 - .gitignore ファイル
👇 以下の既存ファイルを編集(無ければ新規作成)してほしい
📂 kifuwarabe-uec14-practice
├── 📂 greetings
│ └── 📂 japanese
├── 📂 web-service-gin
👉 ├── 📄 .gitignore
└── 📄 go.work
例えば冒頭に追加
# この下に kifuwarabe-uec14 でリポジトリにコミットしないものを追加する
# ---------------------------------------------------------------
go.work
# この上に kifuwarabe-uec14 でリポジトリにコミットしないものを追加する
# ---------------------------------------------------------------
# ...略...
Step [O1o1o0g2o1o0] モジュール作成
👇 カレントディレクトリーは以下の通りとする
👉 📂 kifuwarabe-uec14-practice
├── 📂 greetings
└── 📂 web-service-gin
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go mod init github.com/muzudho/kifuwarabe-uec14-practice
# --------------------------------------------
# 1
# 1. モジュール名。この部分はあなたのレポジトリに合わせて変えてほしい
Output:
go: creating new go.mod: module example/main
go: to add module requirements and sums:
go mod tidy
👇 すると 以下のファイルが自動生成される
📂 kifuwarabe-uec14-practice
├── 📂 greetings
│ └── 📂 japanese
├── 📂 web-service-gin
├── 📄 .gitignore
👉 ├── 📄 go.mod
└── 📄 go.work
module github.com/muzudho/kifuwarabe-uec14-practice
go 1.19
また、モジュールを追加したあとには以下のコマンドを入力してほしい
go mod tidy
ソースから推論して必要なセットアップが自動的に行われるだろう
👇 以下のファイルが自動生成される(コードを書き始めたばかりのときは、無いこともある)
📂 kifuwarabe-uec14-practice
├── 📂 greetings
│ └── 📂 japanese
├── 📂 web-service-gin
├── 📄 .gitignore
├── 📄 go.mod
👉 ├── 📄 go.sum
└── 📄 go.work
Step [O1o1o0g3o0] サンプルプログラム - ハローワールド
Go言語では フォルダーを、ファイルを小分けにするただの入れ物として使うには向いていない。
大量のファイルをトップレベルに置いておくことも気にしないことにする
👇 以下のファイルを新規作成してほしい
📂 kifuwarabe-uec14-practice
├── 📂 greetings
│ └── 📂 japanese
├── 📂 web-service-gin
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
👉 └── 📄 main.go
package main
import (
"flag"
"fmt"
)
func main() {
flag.Parse()
// プログラム名
var name = flag.Arg(0)
if name == "hello" { // [O1o1o0g3o0]
fmt.Println("Hello, World!")
// この上に分岐を挟んでいく
} else {
fmt.Println("go run . {programName}")
}
}
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go work use .
👇 以下のファイルが自動で編集されている
📂 kifuwarabe-uec14-practice
├── 📂 greetings
│ └── 📂 japanese
├── 📂 web-service-gin
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
👉 ├── 📄 go.work
└── 📄 main.go
// ...略...
// * 以下の行が自動追加
use .
📄 go.work
に use .
の行が追加されたことで、カレントディレクトリーは Go言語のワークスペースになった。
制限のかかっていた go run .
コマンドが 再び使えるようになる
👇 以下のファイルが自動生成されている
📂 kifuwarabe-uec14-practice
├── 📂 greetings
│ └── 📂 japanese
├── 📂 web-service-gin
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
👉 ├── 📄 go.work.sum
└── 📄 main.go
github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go run .
Output:
go run . {programName}
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go run . hello
Output:
Hello, World!
Go言語を実行する環境は整ったようだ
Step [O1o1o0g4o_1o0] サンプルプログラム - クォート
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go get rsc.io/quote
Step [O1o1o0g4o0] クォート
👇 以下の既存ファイルを編集してほしい
📂 kifuwarabe-uec14-practice
├── 📂 greetings
│ └── 📂 japanese
├── 📂 web-service-gin
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
👉 └── 📄 main.go
👇 抜粋
import (
// ...略...
// * 以下を追加する
"rsc.io/quote"
)
// ...略...
// * 以下を追加する
} else if name == "quote" { // [O1o1o0g4o0]
fmt.Println(quote.Go())
// この上に分岐を挟んでいく
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go mod tidy
go run . quote
Output:
Don't communicate by sharing memory, share memory by communicating.
以上のようなメッセージが出てくる。
このサンプルプログラムは何をやっているのか分からない。
Step [O1o1o0g5o0] サンプルプログラム - あいさつ
👇 以下のサンプルプログラムの実装を行う
📖 Tutorial: Create a Go module
Step [O1o1o0g5o1o_1o0] カレントディレクトリーの移動
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
cd greetings
📂 kifuwarabe-uec14-practice
👉 ├── 📂 greetings
│ └── 📂 japanese
├── 📂 web-service-gin
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
📂 greetings
へ カレントディレクトリーが移動した
Step [O1o1o0g5o1o_2o0] Goモジュールの作成
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go mod init github.com/muzudho/kifuwarabe-uec14-practice/greetings
👇 以下のファイルが新規作成された
📂 kifuwarabe-uec14-practice
├── 📂 greetings
│ ├── 📂 japanese
👉 │ └── 📄 go.mod
├── 📂 web-service-gin
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
module github.com/muzudho/kifuwarabe-uec14-practice/greetings
go 1.19
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go mod tidy
Step [O1o1o0g5o1o0] あいさつ
👇 以下のファイルを新規作成してほしい
📂 kifuwarabe-uec14-practice
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
👉 │ └── 📄 welcome.go
├── 📂 web-service-gin
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
// BOF [O1o1o0g5o1o0]
package greetings
import "fmt"
// GetMessage returns a greeting for the named person.
func GetMessage(name string) string {
// Return a greeting that embeds the name in a message.
message := fmt.Sprintf("Hi, %v. Welcome!", name)
return message
}
// EOF [O1o1o0g5o1o0]
Step [O1o1o0g5o2o_1o0] ワークスペースズ モードへの登録
👇 ここでカレントディレクトリーはまだ 📂 greetings
だとする
📂 kifuwarabe-uec14-practice
👉 ├── 📂 greetings
└── 📂 web-service-gin
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go work use .
👇 これにより、以下の既存ファイルが自動で編集された
📂 kifuwarabe-uec14-practice
├── 📂 greetings
│ ├── 📂 japanese
│ └── 📄 go.mod
├── 📂 web-service-gin
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
👉 ├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
// ...略...
// * 以下が自動で削除
// use .
// * 以下が自動で追加
use (
.
./greetings
)
これにより、 📄 main.go
から 📄 greetings/welcome.go
ファイル(パッケージ)にパスを通すことができるようになる
Step [O1o1o0g5o2o0] あいさつ
👇 以下の既存ファイルを編集してほしい
📂 kifuwarabe-uec14-practice
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
👉 └── 📄 main.go
import (
// ...略...
// * 以下は、ファイルの保存時に Visual Studio Code の Go エクステンションによって自動で補完される
"github.com/muzudho/kifuwarabe-uec14-practice/greetings"
)
// ...略...
// * 以下を追加する
} else if name == "greetings" { // [O1o1o0g5o2o0]
fmt.Println(greetings.GetMessage("Nanashino Gonbee"))
// この上に分岐を挟んでいく
Step [O1o1o0g5o2o1o0] あいさつ
👇 カレントディレクトリーを戻してほしい
👉 📂 kifuwarabe-uec14-practice
├── 📂 greetings
└── 📂 web-service-gin
👇 そのためのコマンド例
Input:
cd ..
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go mod tidy
go run . greetings
-
go mod tidy
でgo.sum
が自動的に整理される
Output:
Hi, Nanashino Gonbee. Welcome!
Step [O1o1o0g6o0] サンプルプログラム - RESTful API
👇 以下のサンプルプログラムの実装を行う
📖 Tutorial: Developing a RESTful API with Go and Gin
Step [O1o1o0g6o1o_1o0] カレントディレクトリーの移動
👇 カレントディレクトリーを移動してほしい
📂 kifuwarabe-uec14-practice
👉 └── 📂 web-service-gin
👇 そのためのコマンド例
Input:
cd web-service-gin
Step [O1o1o0g6o1o_1o0] Goモジュールの作成
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
go mod init github.com/muzudho/kifuwarabe-uec14-practice/web-service-gin
👇 以下のファイルが自動生成された
📂 kifuwarabe-uec14-practice
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
👉 │ └── 📄 go.mod
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
module github.com/muzudho/kifuwarabe-uec14-practice/web-service-gin
go 1.19
Step [O1o1o0g6o1o_2o0] ワークスペースズ モードへの登録
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
go work use .
👇 これにより、以下の既存ファイルが自動で編集された
📂 kifuwarabe-uec14-practice
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ └── 📄 go.mod
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
👉 ├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
// ...略...
// * 以下が自動で削除
// use (
// .
// ./greetings
// )
// * 以下が自動で追加
use (
.
./greetings
./web-service-gin
)
Step [O1o1o0g6o1o_3o0] カレントディレクトリーを戻す
👇 カレントディレクトリーを移動してほしい
👉 📂 kifuwarabe-uec14-practice
└── 📂 web-service-gin
└── 📄 go.mod
👇 そのためのコマンド例
cd ..
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
go mod tidy
👇 これにより、以下の既存ファイルが自動で編集、または生成された
📂 kifuwarabe-uec14-practice
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
👉 │ ├── 📄 go.mod
👉 │ └── 📄 go.sum
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
内容は行数が多いので省略
Step [O1o1o0g6o1o0] データの作成
👇 カレントディレクトリーを移動してほしい
📂 kifuwarabe-uec14-practice
👉 └── 📂 web-service-gin
👇 そのためのコマンド
cd web-service-gin
Step [O1o1o0g6o2o0] ビューおよびルート作成 - web-service-gin/main.go
👇 以下のファイルを新規作成してほしい
📂 kifuwarabe-uec14-practice
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
👉 │ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
// BOF [O1o1o0g6o2o0]
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
// album represents data about a record album.
type album struct {
ID string `json:"id"`
Title string `json:"title"`
Artist string `json:"artist"`
Price float64 `json:"price"`
}
// albums slice to seed record album data.
var albums = []album{
{ID: "1", Title: "Blue Train", Artist: "John Coltrane", Price: 56.99},
{ID: "2", Title: "Jeru", Artist: "Gerry Mulligan", Price: 17.99},
{ID: "3", Title: "Sarah Vaughan and Clifford Brown", Artist: "Sarah Vaughan", Price: 39.99},
}
// getAlbums responds with the list of all albums as JSON.
func getAlbums(c *gin.Context) {
c.IndentedJSON(http.StatusOK, albums)
}
// getAlbumByID locates the album whose ID value matches the id
// parameter sent by the client, then returns that album as a response.
func getAlbumByID(c *gin.Context) {
id := c.Param("id")
// Loop over the list of albums, looking for
// an album whose ID value matches the parameter.
for _, a := range albums {
if a.ID == id {
c.IndentedJSON(http.StatusOK, a)
return
}
}
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "album not found"})
}
// postAlbums adds an album from JSON received in the request body.
func postAlbums(c *gin.Context) {
var newAlbum album
// Call BindJSON to bind the received JSON to
// newAlbum.
if err := c.BindJSON(&newAlbum); err != nil {
return
}
// Add the new album to the slice.
albums = append(albums, newAlbum)
c.IndentedJSON(http.StatusCreated, newAlbum)
}
func main() {
router := gin.Default()
router.GET("/albums", getAlbums)
router.GET("/albums/:id", getAlbumByID)
router.POST("/albums", postAlbums)
router.Run("localhost:8080")
}
// EOF [O1o1o0g6o2o0]
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
go get .
必要なパッケージが自動的にダウンロードされるのだろう
Step [O1o1o0g6o3o_1o0] 実行
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go run .
Output:
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET /albums --> main.getAlbums (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on localhost:8080
Step [O1o1o0g6o3o_2o0] Webアクセス
👇 ブラウザを開いてアクセスしてほしい
📖 http://localhost:8080/albums
👇 画面に以下のように表示されるだろう
[
{
"id": "1",
"title": "Blue Train",
"artist": "John Coltrane",
"price": 56.99
},
{
"id": "2",
"title": "Jeru",
"artist": "Gerry Mulligan",
"price": 17.99
},
{
"id": "3",
"title": "Sarah Vaughan and Clifford Brown",
"artist": "Sarah Vaughan",
"price": 39.99
}
]
👇 ブラウザを開いてアクセスしてほしい
📖 http://localhost:8080/albums/2
👇 画面に以下のように表示されるだろう
{
"id": "2",
"title": "Jeru",
"artist": "Gerry Mulligan",
"price": 17.99
}
[Ctrl] + [C]
キーでサーバーを止めてほしい
Step [O1o1o0g6o3o0] カレントディレクトリーを戻す
👇 カレントディレクトリーを移動してほしい
👉 📂 kifuwarabe-uec14-practice
└── 📂 web-service-gin
👇 そのためのコマンドの例
cd ..
Step [O1o1o0g7o0] サンプルプログラム - ジェネリクス
👇 以下のサンプルプログラムの実装を行う
📖 Tutorial: Getting started with generics
Step [O1o1o0g7o1o0] フォルダー作成
👇 以下のフォルダーを新規作成してほしい
📂 kifuwarabe-uec14-practice
👉 ├── 📂 generics
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
Step [O1o1o0g7o2o0] カレントディレクトリーを移動
👇 コマンドラインのプロンプトを見てほしい
C:\Users\むずでょ\go\src\github.com\muzudho\kifuwarabe-uec14-practice>
# ------------------------------------------------------------------
# 11
# -------------------------------------------------------------------
# 10
#
# 10. (`C:` も含めて)これがプロンプト
# 11. カレントディレクトリー
👇 現在のカレントディレクトリーが以下とする
👉 📂 kifuwarabe-uec14-practice
└── 📂 generics
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
cd generics
👇 コマンドラインのプロンプトを見てほしい
C:\Users\むずでょ\go\src\github.com\muzudho\kifuwarabe-uec14-practice\generics>
👇 カレントディレクトリーは移動した
📂 kifuwarabe-uec14-practice
👉 └── 📂 generics
Step [O1o1o0g7o3o0] Goモジュールの作成
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
go mod init github.com/muzudho/kifuwarabe-uec14-practice/generics
👇 以下のファイルが自動生成された
📂 kifuwarabe-uec14-practice
├── 📂 generics
👉 │ └── 📄 go.mod
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
module github.com/muzudho/kifuwarabe-uec14-practice/generics
go 1.19
Step [O1o1o0g7o4o0] ワークスペースズ モードへの登録
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
go work use .
👇 これにより、以下の既存ファイルが自動で編集された
📂 kifuwarabe-uec14-practice
├── 📂 generics
│ └── 📄 go.mod
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
👉 ├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
// ...略...
// * 以下が自動で削除
// use (
// .
// ./greetings
// ./web-service-gin
// )
// * 以下が自動で追加
use (
.
./generics
./greetings
./web-service-gin
)
Step [O1o1o0g7o5o0] プログラム作成
👇 以下のファイルを新規作成してほしい
📂 kifuwarabe-uec14-practice
├── 📂 generics
│ ├── 📄 go.mod
👉 │ └── 📄 main.go
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
// BOF [O1o1o0g7o5o0]
package main
import "fmt"
type Number interface {
int64 | float64
}
func main() {
// Initialize a map for the integer values
ints := map[string]int64{
"first": 34,
"second": 12,
}
// Initialize a map for the float values
floats := map[string]float64{
"first": 35.98,
"second": 26.99,
}
fmt.Printf("Non-Generic Sums: %v and %v\n",
SumInts(ints),
SumFloats(floats))
fmt.Printf("Generic Sums: %v and %v\n",
SumIntsOrFloats[string, int64](ints),
SumIntsOrFloats[string, float64](floats))
fmt.Printf("Generic Sums, type parameters inferred: %v and %v\n",
SumIntsOrFloats(ints),
SumIntsOrFloats(floats))
fmt.Printf("Generic Sums with Constraint: %v and %v\n",
SumNumbers(ints),
SumNumbers(floats))
}
// SumInts adds together the values of m.
func SumInts(m map[string]int64) int64 {
var s int64
for _, v := range m {
s += v
}
return s
}
// SumFloats adds together the values of m.
func SumFloats(m map[string]float64) float64 {
var s float64
for _, v := range m {
s += v
}
return s
}
// SumIntsOrFloats sums the values of map m. It supports both floats and integers
// as map values.
func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V {
var s V
for _, v := range m {
s += v
}
return s
}
// SumNumbers sums the values of map m. Its supports both integers
// and floats as map values.
func SumNumbers[K comparable, V Number](m map[K]V) V {
var s V
for _, v := range m {
s += v
}
return s
}
// EOF [O1o1o0g7o5o0]
Step [O1o1o0g7o6o0] カレントディレクトリーを移動
👇 カレントディレクトリーを移動してほしい
👉 📂 kifuwarabe-uec14-practice
└── 📂 generics
👇 そのためのコマンドの例
cd ../
Step [O1o1o0g7o7o0] tidy
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go mod tidy
👇 これにより、以下の既存ファイルが自動で編集、または生成された
📂 kifuwarabe-uec14-practice
├── 📂 generics
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
👉 ├── 📄 go.mod
👉 ├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
内容は行数が多いので省略
Step [O1o1o0g7o8o0] カレントディレクトリーを移動
👇 カレントディレクトリーを移動してほしい
📂 kifuwarabe-uec14-practice
👉 └── 📂 generics
👇 そのためのコマンドの例
cd generics
Step [O1o1o0g7o9o0] 実行
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go run .
Output:
Non-Generic Sums: 46 and 62.97
Generic Sums: 46 and 62.97
Generic Sums, type parameters inferred: 46 and 62.97
Generic Sums with Constraint: 46 and 62.97
Step [O1o1o0g8o0] サンプルプログラム - Fussing
👇 以下のサンプルプログラムの実装を行う
📖 Tutorial: Getting started with fuzzing
Step [O1o1o0g8o1o0] フォルダー作成
👇 以下のフォルダーを新規作成してほしい
📂 kifuwarabe-uec14-practice
👉 ├── 📂 fuzz
├── 📂 generics
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
Step [O1o1o0g8o2o0] カレントディレクトリーを移動
👇 現在のカレントディレクトリーが以下とする
👉 📂 kifuwarabe-uec14-practice
└── 📂 fuzz
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
cd fuzz
👇 カレントディレクトリーは移動した
📂 kifuwarabe-uec14-practice
👉 └── 📂 fuzz
Step [O1o1o0g8o3o0] Goモジュールの作成
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
go mod init github.com/muzudho/kifuwarabe-uec14-practice/fuzz
👇 以下のファイルが自動生成された
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
👉 │ └── 📄 go.mod
├── 📂 generics
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
module github.com/muzudho/kifuwarabe-uec14-practice/fuzz
go 1.19
Step [O1o1o0g8o4o0] ワークスペースズ モードへの登録
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
go work use .
👇 これにより、以下の既存ファイルが自動で編集された
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
👉 │ └── 📄 go.mod
├── 📂 generics
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
// ...略...
// * 以下が自動で削除
// use (
// .
// ./generics
// ./greetings
// ./web-service-gin
// )
// * 以下が自動で追加
use (
.
./fuzz
./generics
./greetings
./web-service-gin
)
Step [O1o1o0g8o5o0] プログラム作成
👇 以下のファイルを新規作成してほしい
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
│ ├── 📄 go.mod
👉 │ └── 📄 main.go
├── 📂 generics
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
// BOF [O1o1o0g8o5o0]
package main
import (
"errors"
"fmt"
"unicode/utf8"
)
func main() {
input := "The quick brown fox jumped over the lazy dog"
rev, revErr := Reverse(input)
doubleRev, doubleRevErr := Reverse(rev)
fmt.Printf("original: %q\n", input)
fmt.Printf("reversed: %q, err: %v\n", rev, revErr)
fmt.Printf("reversed again: %q, err: %v\n", doubleRev, doubleRevErr)
}
func Reverse(s string) (string, error) {
if !utf8.ValidString(s) {
return s, errors.New("input is not valid UTF-8")
}
r := []rune(s)
for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
r[i], r[j] = r[j], r[i]
}
return string(r), nil
}
// EOF [O1o1o0g8o5o0]
Step [O1o1o0g8o5o1o0] プログラム作成
👇 以下のファイルを新規作成してほしい
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
│ ├── 📄 go.mod
│ ├── 📄 main.go
👉 │ └── 📄 reverse_test.go
├── 📂 generics
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
// BOF [O1o1o0g8o5o1o0]
package main
import (
"testing"
"unicode/utf8"
)
func FuzzReverse(f *testing.F) {
testcases := []string{"Hello, world", " ", "!12345"}
for _, tc := range testcases {
f.Add(tc) // Use f.Add to provide a seed corpus
}
f.Fuzz(func(t *testing.T, orig string) {
rev, err1 := Reverse(orig)
if err1 != nil {
return
}
doubleRev, err2 := Reverse(rev)
if err2 != nil {
return
}
if orig != doubleRev {
t.Errorf("Before: %q, after: %q", orig, doubleRev)
}
if utf8.ValidString(orig) && !utf8.ValidString(rev) {
t.Errorf("Reverse produced invalid UTF-8 string %q", rev)
}
})
}
// EOF [O1o1o0g8o5o1o0]
Step [O1o1o0g8o6o0] 実行
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go run .
Output:
original: "The quick brown fox jumped over the lazy dog"
reversed: "god yzal eht revo depmuj xof nworb kciuq ehT", err: <nil>
reversed again: "The quick brown fox jumped over the lazy dog", err: <nil>
Step [O1o1o0g8o7o0] テスト
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go test
Output:
PASS
ok github.com/muzudho/kifuwarabe-uec14-practice/fuzz 0.219s
Step [O1o1o0g9o0] サンプルプログラム - Wiki
👇 以下のサンプルプログラムの実装を行う
Step [O1o1o0g9o1o0] フォルダー作成
👇 以下のフォルダーを新規作成してほしい
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
│ ├── 📄 go.mod
│ ├── 📄 main.go
│ └── 📄 reverse_test.go
├── 📂 generics
│ ├── 📄 go.mod
│ └── 📄 main.go
👉 ├── 📂 gowiki
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
Step [O1o1o0g9o2o0] カレントディレクトリーを移動
👇 現在のカレントディレクトリーが以下とする
👉 📂 kifuwarabe-uec14-practice
└── 📂 gowiki
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
cd gowiki
👇 カレントディレクトリーは移動した
📂 kifuwarabe-uec14-practice
👉 └── 📂 gowiki
Step [O1o1o0g9o3o0] Goモジュールの作成
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
go mod init github.com/muzudho/kifuwarabe-uec14-practice/gowiki
👇 以下のファイルが自動生成された
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
│ ├── 📄 go.mod
│ ├── 📄 main.go
│ └── 📄 reverse_test.go
├── 📂 generics
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 gowiki
👉 │ └── 📄 go.mod
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
module github.com/muzudho/kifuwarabe-uec14-practice/gowiki
go 1.19
Step [O1o1o0g9o4o0] ワークスペースズ モードへの登録
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
go work use .
👇 これにより、以下の既存ファイルが自動で編集された
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
│ ├── 📄 go.mod
│ ├── 📄 main.go
│ └── 📄 reverse_test.go
├── 📂 generics
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 gowiki
│ └── 📄 go.mod
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
👉 ├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
// ...略...
// * 以下が自動で削除
// use (
// .
// ./fuzz
// ./generics
// ./greetings
// ./web-service-gin
// )
// * 以下が自動で追加
use (
.
./fuzz
./generics
./gowiki
./greetings
./web-service-gin
)
Step [O1o1o0g9o5o0] Vol1 プログラム作成
👇 以下のファイルを新規作成してほしい
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
│ ├── 📄 go.mod
│ ├── 📄 main.go
│ └── 📄 reverse_test.go
├── 📂 generics
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 gowiki
│ ├── 📄 go.mod
👉 │ └── 📄 wiki.go
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
// BOF [O1o1o0g9o5o0]
package main
import (
"flag"
"fmt"
"os"
)
type Page struct {
Title string
Body []byte
}
func (p *Page) save() error {
filename := p.Title + ".txt"
return os.WriteFile(filename, p.Body, 0600)
}
func loadPage(title string) (*Page, error) {
filename := title + ".txt"
body, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
return &Page{Title: title, Body: body}, nil
}
func main() {
flag.Parse()
// プログラム名
var name = flag.Arg(0)
if name == "vol1" { // [O1o1o0g9o5o0]
p1 := &Page{Title: "TestPage", Body: []byte("This is a sample Page.")}
p1.save()
p2, _ := loadPage("TestPage")
fmt.Println(string(p2.Body))
// この上に分岐を挟んでいく
} else {
fmt.Println("go run . {programName}")
}
}
// EOF [O1o1o0g9o5o0]
Step [O1o1o0g9o6o0] 実行
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go run . vol1
Output:
This is a sample Page.
👇 以下のファイルが自動生成された
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
│ ├── 📄 go.mod
│ ├── 📄 main.go
│ └── 📄 reverse_test.go
├── 📂 generics
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 gowiki
│ ├── 📄 go.mod
👉 │ ├── 📄 TestPage.txt
│ └── 📄 wiki.go
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
Step [O1o1o0g9o7o_1o0] Vol2 プログラム作成 - simple.go
👇 以下のファイルを新規作成してほしい
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
│ ├── 📄 go.mod
│ ├── 📄 main.go
│ └── 📄 reverse_test.go
├── 📂 generics
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 gowiki
│ ├── 📄 go.mod
👉 │ ├── 📄 simple.go
│ ├── 📄 TestPage.txt
│ └── 📄 wiki.go
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
// BOF [O1o1o0g9o7o_1o0]
package main
import (
"fmt"
"net/http"
)
func SimpleHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}
// EOF [O1o1o0g9o7o_1o0]
先頭行に //go:build ignore
と書くと Go言語のビルド対象から外れるようだが、
ビルド対象に含めることにした
Step [O1o1o0g9o7o_2o0] プログラム編集
👇 以下の既存ファイルを編集してほしい
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
│ ├── 📄 go.mod
│ ├── 📄 main.go
│ └── 📄 reverse_test.go
├── 📂 generics
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 gowiki
│ ├── 📄 go.mod
│ ├── 📄 simple.go
│ ├── 📄 TestPage.txt
👉 │ └── 📄 wiki.go
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
👇 抜粋
// ...略...
// * 以下を追加する
} else if name == "vol2" { // [O1o1o0g9o7o_2o0]
http.HandleFunc("/", SimpleHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
// この上に分岐を挟んでいく
Step [O1o1o0g9o7o_3o0] 実行
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go run . vol2
Step [O1o1o0g9o7o_4o0] Webアクセス
👇 ブラウザを開いてアクセスしてほしい
📖 http://localhost:8080/albums
👇 画面に以下のように表示されるだろう
Hi there, I love albums!
Step [O1o1o0g9o7o_5o0] Webアクセス
👇 ブラウザを開いてアクセスしてほしい
📖 http://localhost:8080/monkeys
👇 画面に以下のように表示されるだろう
Hi there, I love monkeys!
Step [O1o1o0g9o7o0] Vol3 プログラム作成
👇 以下のファイルを新規作成してほしい
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
│ ├── 📄 go.mod
│ ├── 📄 main.go
│ └── 📄 reverse_test.go
├── 📂 generics
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 gowiki
│ ├── 📄 go.mod
│ ├── 📄 simple.go
│ ├── 📄 TestPage.txt
👉 │ ├── 📄 view.go
│ └── 📄 wiki.go
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
// BOF [O1o1o0g9o7o0]
package main
import (
"fmt"
"net/http"
)
func ViewHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[len("/view/"):]
p, err := loadPage(title)
if err != nil {
panic(err)
}
fmt.Fprintf(w, "<h1>%s</h1><div>%s</div>", p.Title, p.Body)
}
// EOF [O1o1o0g9o7o0]
Step [O1o1o0g9o8o0] プログラム編集
👇 以下の既存ファイルを編集してほしい
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
│ ├── 📄 go.mod
│ ├── 📄 main.go
│ └── 📄 reverse_test.go
├── 📂 generics
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 gowiki
│ ├── 📄 go.mod
│ ├── 📄 simple.go
│ ├── 📄 TestPage.txt
│ ├── 📄 view.go
👉 │ └── 📄 wiki.go
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
👇 抜粋
// ...略...
// * 以下を追加する
} else if name == "vol3" { // [O1o1o0g9o8o0]
http.HandleFunc("/view/", ViewHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
// この上に分岐を挟んでいく
Step [O1o1o0g9o9o_1o0] ページ作成
👇 以下のファイルを新規作成してほしい
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
│ ├── 📄 go.mod
│ ├── 📄 main.go
│ └── 📄 reverse_test.go
├── 📂 generics
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 gowiki
│ ├── 📄 go.mod
│ ├── 📄 simple.go
👉 │ ├── 📄 test.txt
│ ├── 📄 TestPage.txt
│ ├── 📄 view.go
│ └── 📄 wiki.go
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
Hello world
Step [O1o1o0g9o9o0] ビルド
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go build .
カレントディレクトリーにある *.go
ファイルをビルドしました
👇 以下のファイルが自動生成された
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
│ ├── 📄 go.mod
│ ├── 📄 main.go
│ └── 📄 reverse_test.go
├── 📂 generics
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 gowiki
│ ├── 📄 go.mod
👉 │ ├── 📄 gowiki.exe
│ ├── 📄 simple.go
│ ├── 📄 TestPage.txt
│ ├── 📄 view.go
│ └── 📄 wiki.go
├── 📂 greetings
│ ├── 📂 japanese
│ ├── 📄 go.mod
│ └── 📄 welcome.go
├── 📂 web-service-gin
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ └── 📄 main.go
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
Step [O1o1o0g9o10o0] 実行
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
# Windows
gowiki.exe vol3
Step [O1o1o0g9o11o0] Webアクセス
👇 ブラウザを開いてアクセスしてほしい
📖 http://localhost:8080/view/test
👇 画面に以下のように表示されるだろう
test
Hello world
Step [O1o1o0g10o0] ロギング
👇 公式のサンプルを一旦離れて ロギングを練習する
📖 Zap
Step [O1o1o0g10o1o0] フォルダー作成
👇 以下のフォルダーを新規作成してほしい
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
├── 📂 generics
├── 📂 gowiki
├── 📂 greetings
👉 ├── 📂 logging
├── 📂 web-service-gin
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
Step [O1o1o0g10o2o0] カレントディレクトリーを移動
👇 コマンドラインのプロンプトを見てほしい
C:\Users\むずでょ\go\src\github.com\muzudho\kifuwarabe-uec14-practice>
# ------------------------------------------------------------------
# 11
# -------------------------------------------------------------------
# 10
#
# 10. (`C:` も含めて)これがプロンプト
# 11. カレントディレクトリー
👇 現在のカレントディレクトリーが以下とする
👉 📂 kifuwarabe-uec14-practice
└── 📂 logging
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
cd logging
👇 コマンドラインのプロンプトを見てほしい
C:\Users\むずでょ\go\src\github.com\muzudho\kifuwarabe-uec14-practice\logging>
👇 カレントディレクトリーは移動した
📂 kifuwarabe-uec14-practice
👉 └── 📂 logging
Step [O1o1o0g10o3o0] Goモジュールの作成
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go mod init github.com/muzudho/kifuwarabe-uec14-practice/logging
Output:
go: creating new go.mod: module github.com/muzudho/kifuwarabe-uec14-practice/logging
👇 以下のファイルが自動生成された
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
├── 📂 generics
├── 📂 gowiki
├── 📂 greetings
├── 📂 logging
👉 │ └── 📄 go.mod
├── 📂 web-service-gin
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
module github.com/muzudho/kifuwarabe-uec14-practice/logging
go 1.19
Step [O1o1o0g10o4o0] ワークスペースズ モードへの登録
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
go work use .
👇 これにより、以下の既存ファイルが自動で編集された
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
├── 📂 generics
├── 📂 gowiki
├── 📂 greetings
├── 📂 logging
│ └── 📄 go.mod
├── 📂 web-service-gin
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
👉 ├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
// ...略...
use (
// ...略...
./logging
// ...略...
)
Step [O1o1o0g10o5o_1o0] インストール
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go get -u go.uber.org/zap
Step [O1o1o0g10o5o_2o0] 設定 - .gitignore ファイル
👇 以下の既存ファイルを編集してほしい
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
├── 📂 generics
├── 📂 gowiki
├── 📂 greetings
├── 📂 logging
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 web-service-gin
👉 ├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
# この下に kifuwarabe-uec14 でリポジトリにコミットしないものを追加する
# ---------------------------------------------------------------
# ...略...
*.log
# この上に kifuwarabe-uec14 でリポジトリにコミットしないものを追加する
# ---------------------------------------------------------------
# ...略...
Step [O1o1o0g10o5o0] メインプログラム作成
👇 以下のファイルを新規作成してほしい
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
├── 📂 generics
├── 📂 gowiki
├── 📂 greetings
├── 📂 logging
│ ├── 📄 go.mod
👉 │ └── 📄 main.go
├── 📂 web-service-gin
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
// BOF [O1o1o0g10o5o0]
package main
import (
"log"
"os"
"time"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
// createLoggerForConsole - ロガー作成,コンソール用
func createLoggerForConsole(logFile *os.File) *zap.Logger {
// 設定,コンソール用
var config1 = zapcore.EncoderConfig{
MessageKey: "message",
// LevelKey: "level",
// EncodeLevel: zapcore.CapitalLevelEncoder,
TimeKey: "time",
EncodeTime: zapcore.ISO8601TimeEncoder, // 日本時間のタイムスタンプ
// CallerKey: "caller",
// EncodeCaller: zapcore.ShortCallerEncoder,
}
// config1.EncodeTime = zapcore.ISO8601TimeEncoder // 日本時間のタイムスタンプ
// 設定,ファイル用
var config2 = zap.NewProductionEncoderConfig()
config2.EncodeTime = zapcore.ISO8601TimeEncoder // 日本時間のタイムスタンプ
// コア
var core = zapcore.NewTee(
zapcore.NewCore(
zapcore.NewConsoleEncoder(config1), // コンソール形式
zapcore.Lock(os.Stderr), // 出力先は標準エラー
zapcore.DebugLevel), // ログレベル
zapcore.NewCore(
zapcore.NewConsoleEncoder(config2), // コンソール形式
zapcore.AddSync(logFile), // 出力先はログファイル
zapcore.DebugLevel), // ログレベル
)
// ロガーのビルド
return zap.New(core, zap.AddCaller(), zap.AddStacktrace(zapcore.ErrorLevel))
}
// createLoggerForJson - ロガー作成,複数行JSON形式
func createLoggerAsJson(logFile *os.File) *zap.Logger {
// 設定
var config = zap.NewProductionEncoderConfig()
config.EncodeTime = zapcore.ISO8601TimeEncoder // 日本時間のタイムスタンプ
// コア
var core = zapcore.NewTee(
zapcore.NewCore(
zapcore.NewJSONEncoder(config), // JSON形式
zapcore.AddSync(logFile), // 出力先はログファイル
zapcore.DebugLevel), // ログレベル
)
// ロガーのビルド
return zap.New(core, zap.AddCaller(), zap.AddStacktrace(zapcore.ErrorLevel))
}
// func createLogger2(logFile *os.File) *zap.Logger {
// // ロガー作成
// // logger, _ := zap.NewDevelopment() // 開発用
// logger, _ := zap.NewProduction() // 製品用
// // ロガー破棄時にバッファーをフラッシュする
// defer logger.Sync() // flushes buffer, if any
// return logger
// }
func main() {
// ファイル,基本
basicLogFile, _ := os.OpenFile("example-basic.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
defer basicLogFile.Close() // ログファイル使用済み時にファイルを閉じる
// `log` インターフェースを直接使うなら
log.SetOutput(basicLogFile) // ロガーにログファイルを紐づけ
log.Println("Hello, world!")
// ファイル,コンソール用
logcFile, _ := os.OpenFile("example.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
defer logcFile.Close() // ログファイル使用済み時にファイルを閉じる
// ファイル,複数行JSON形式
logjFile, _ := os.OpenFile("example-json.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
defer logcFile.Close() // ログファイル使用済み時にファイルを閉じる
// カスタマイズしたロガーを使うなら
var logc = createLoggerForConsole(logcFile).Sugar()
var logj = createLoggerAsJson(logjFile).Sugar()
// Run
var url = "http://tic.warabenture.com"
logc.Infof("Failed to fetch URL: %s", url)
logj.Infow("failed to fetch URL",
// Structured context as loosely typed key-value pairs.
"url", url,
"attempt", 3,
"backoff", time.Second,
)
}
// EOF [O1o1o0g10o5o0]
Step [O1o1o0g10o6o0] 実行
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go run .
Output:
2022-09-11T14:36:31.819+0900 Failed to fetch URL: http://tic.warabenture.com
👇 以下のファイルが自動生成された
📂 kifuwarabe-uec14-practice
├── 📂 fuzz
├── 📂 generics
├── 📂 gowiki
├── 📂 greetings
├── 📂 logging
👉 │ ├── 📄 example-basic.log
👉 │ ├── 📄 example-json.log
👉 │ ├── 📄 example.log
│ ├── 📄 go.mod
│ └── 📄 main.go
├── 📂 web-service-gin
├── 📄 .gitignore
├── 📄 go.mod
├── 📄 go.sum
├── 📄 go.work
├── 📄 go.work.sum
└── 📄 main.go
👇 📄 example-basic.log
2022/09/11 14:30:26 Hello, world!
👇 📄 example-json.log
{"level":"info","ts":"2022-09-11T14:30:26.223+0900","caller":"logging/main.go:93","msg":"failed to fetch URL","url":"http://tic.warabenture.com","attempt":3,"backoff":1}
👇 📄 example.log
2022-09-11T14:30:26.222+0900 info logging/main.go:92 Failed to fetch URL: http://tic.warabenture.com
- 作成されるログファイルは JSON形式ではない。 ワンライナーのJSONが複数行並ぶ
次の記事
📖 Go [O1o1o0] 目指せ!第14回UEC杯コンピューター囲碁大会<本編>
参考にした記事
📖 Go [O1o1o0] 目指せ!第14回UEC杯コンピューター囲碁大会 - この記事
Go言語
モジュール
マルチ ワークスペース
📖 Setting up your workspace
📖 Go 1.18集中連載 Workspacesモードを試してみた
ロギング
📖 How to log to stdout or stderr based on log level using uber-go/zap?
📖 5 structured logging packages for Go
📖 Structured Logging in Golang with Zap – Blazing Fast Logger
📖 【Go】ログライブラリzapを使う時はglobal loggerが便利!
📖 GolangのLogger「zap」の最低限の設定方法
📖 zapでログレベルでログの出力先を振り分ける方法
📖 golangの高速な構造化ログライブラリ「zap」の使い方
📖 GoのロギングライブラリzapのTips
📖 golang zap v1.0.0 でログの日付をJSTで表示する方法
📖 Using Zap - Creating custom loggers
Go言語と Visual Studio Code
go.work
📖 Tutorial: Getting started with multi-module workspaces
📖 VSCodeを開いたときのgoplsのmoduleに関するエラー
📖 Setting up your workspace
おわり