このチュートリアルでは、Go、SQLite、基本的な HTML/JavaScript フォームを使用してメモを追加および削除する簡単なメモアプリケーションを作成する手順を説明します。
前提条件
マシンにインストールされた Go (バージョン 1.16 以上)
GoLand – ほとんどのバージョンで問題ありません。 このチュートリアルは GoLand 2024.2 を使用して作成されました。
cgo を有効にするための C コンパイラー。 このチュートリアルで使用する SQLite ドライバーには cgo が必要です。
SQLite ドライバーをダウンロードするためのインターネット接続。
ステップ 1: プロジェクトを初期化する
プロジェクト用の新しいディレクトリを作成し、Go モジュールを初期化します。
をクリックしてください。
または、 %instance% へようこそ 画面で 新規プロジェクト をクリックします。
新規プロジェクト ダイアログで、 Go を選択します。
ロケーション フィールドに、プロジェクトを保存する場所を入力するか、その場所に移動します。
GOROOT フィールドで、Go のインストール場所を指定します。 GoLand は通常、この場所を自動的に検出します。
Go SDK の新しいバージョンを変更またはインストールするには、 SDK の追加 (
) をクリックし、次のいずれかのオプションを選択します。
サンプルコードの追加 チェックボックスをクリアします。 開始する前にオンボーディングのヒントが必要な場合は、このチェックボックスをそのままにしておきます。
作成 をクリックしてください。
GoLand はプロジェクトフォルダーを作成し、プロジェクトを初期化して、次の Bash アクションをユーザーの代わりに実行します:
mkdir notes-app
cd notes-app
go mod init notes-app
ステップ 2: データベースを設定する
ここで、 database.go という名前の新しいファイルを作成しましょう。 このファイルでは、SQLite データベース接続を設定します。 全体的な構成には、データベースファイル ( notes.db ) と、情報を保存する notes テーブルの作成が含まれます。
プロジェクトのルートディレクトリに、次の内容の database.go を作成します。
package main
import (
"database/sql"
"log"
// Import the SQLite driver anonymously to initialize it
// without directly referencing
_ "github.com/mattn/go-sqlite3"
)
// Declare a global variable to hold the database connection pool
var db *sql.DB
// initDB initializes the database connection and creates
// the 'notes' table if it doesn't exist
func initDB() {
var err error
// Open a connection to the SQLite database file named "notes.db"
db, err = sql.Open("sqlite3", "./notes.db")
if err != nil {
// Log any error that occurs and terminate the program
log.Fatal(err)
}
// SQL statement to create the notes table if it doesn't exist
createTable := `
CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT,
content TEXT
);`
// Execute the SQL statement to create the table
_, err = db.Exec(createTable)
if err != nil {
// Log any error that occurs while executing the SQL statement
// and terminate the program
log.Fatal(err)
}
}
以下の手順に従って、ファイル作成のプロセスを進めていきます。
Go ファイルを作成する
Go ファイルを作成するには、次のいずれかのオプションを使用します。
プロジェクト ツールウィンドウで、プロジェクトの親フォルダーを右クリックし、 を選択します。
プロジェクトの親フォルダーをクリックし、 Alt+Insert を押して、 Go ファイル を選択します。
プロジェクトの親フォルダーをクリックし、 に移動します。
新規 Go ファイル ダイアログでファイル名を入力し、ファイルの種類を選択します。
ステップ 3: Note 構造体を作成する
note.go という名前の 新しいファイルを作成し、 Note 構造体を定義します。
Note 構造体は、ID、タイトル、コンテンツを含むメモの構造を定義します。 この構造体は、アプリケーションでメモを明確かつ整理された方法で表現できるようにします。
package main
type Note struct {
ID int
Title string
Content string
}
また、データベースとやりとりする場合、データを構造的に処理する方法が重要です。 Note 構造体を使用すると、データベースの行を Go オブジェクトにマッピングしたり、その逆を行ったりできます。 例: データベースからメモを取得する場合、各行を Note 構造体にスキャンできます。
ステップ 4: データベース操作を実装する
メモを作成、読み取り、削除するデータベース操作を note.go に追加します。
作成 操作は、データベースに新しいレコードまたはデータエントリを追加するために使用されます。 SQL では、これは通常、INSERT ステートメントを使用して実行されます。
func CreateNote(title, content string) {
query := `INSERT INTO notes (title, content) VALUES (?, ?)`
_, err := db.Exec(query, title, content)
if err != nil {
log.Fatal(err)
}
}
Read 操作は、データベースから既存のレコードまたはデータを取得するために使用されます。 SQL では、これは通常、SELECT ステートメントを使用して実行されます。
func GetNotes() ([]Note, error) {
rows, err := db.Query("SELECT id, title, content FROM notes")
if err != nil {
return nil, err
}
defer rows.Close()
var notes []Note
for rows.Next() {
var note Note
err = rows.Scan(¬e.ID, ¬e.Title, ¬e.Content)
if err != nil {
return nil, err
}
notes = append(notes, note)
}
return notes, nil
}
削除 操作は、データベースから既存のレコードまたはデータを削除するために使用されます。 SQL では、これは通常、DELETE ステートメントを使用して実行されます。
func DeleteNote(id int) {
query := `DELETE FROM notes WHERE id = ?`
_, err := db.Exec(query, id)
if err != nil {
log.Fatal(err)
}
}
package main
import (
"log"
)
type Note struct {
ID int
Title string
Content string
}
// CreateNote adds a new note to the database
func CreateNote(title, content string) {
query := `INSERT INTO notes (title, content) VALUES (?, ?)`
_, err := db.Exec(query, title, content)
if err != nil {
log.Fatal(err)
}
}
// GetNotes retrieves all notes from the database
func GetNotes() ([]Note, error) {
rows, err := db.Query("SELECT id, title, content FROM notes")
if err != nil {
return nil, err
}
defer rows.Close()
var notes []Note
for rows.Next() {
var note Note
err = rows.Scan(¬e.ID, ¬e.Title, ¬e.Content)
if err != nil {
return nil, err
}
notes = append(notes, note)
}
return notes, nil
}
// DeleteNote removes a note from the database
func DeleteNote(id int) {
query := `DELETE FROM notes WHERE id = ?`
_, err := db.Exec(query, id)
if err != nil {
log.Fatal(err)
}
}
ステップ 5: メイン関数を作成する
ここで、 main.go を変更して、そこに main 関数を追加しましょう。 main.go のコードは、メモの表示、新しいメモの追加、既存のメモの削除を行うルートを備えた基本的な Web サーバーをセットアップします。 SQLite データベースを使用してメモを保存し、メモを作成、読み取り、削除する HTTP リクエストを処理します。
HTTP リクエストを処理するには、ハンドラーを使用します。 Go の HTTP ハンドラーは、HTTP リクエストを処理する関数です。 これらは、Go で Web サーバーを作成するための構成要素です。 HTTP ハンドラーは、HTTP リクエストを受け取り、処理して、HTTP レスポンスを生成します。 Go では、これらのハンドラーは、 http.Handler インターフェースを満たす関数またはメソッドであるか、 http.HandleFunc などの関数に直接渡されます。
まず main 関数から始めます。
機能: メイン
main 関数は次の機能を実行します。
プログラムを実行すると、コードによってサーバーが開始されます。サーバーはポート 8080 で起動し、エラーが発生するとログに記録され、プログラムが終了します。
func main() {
// Initialize the database
initDB()
// Ensure the database connection is closed when the main function exits
defer db.Close()
// Set up HTTP handlers for different routes
http.HandleFunc("/", indexHandler) // Route for the homepage
http.HandleFunc("/add", addHandler) // Route for adding a new note
http.HandleFunc("/delete", deleteHandler) // Route for deleting a note
// Log the server start and listen on port 8080
log.Println("Server started at :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
機能: インデックスハンドラー
インデックスハンドラーはいくつかの機能を実行します。
メモの取得: GetNotes() を呼び出して、データベースからすべてのメモを取得します。 エラーが発生した場合は、内部サーバーエラー応答を送信します。
テンプレートの解析: index.html テンプレートファイルを解析します。 テンプレートの解析中にエラーが発生した場合は、内部サーバーエラー応答を送信します。
テンプレートの実行: 取得したメモを使用してテンプレートを実行し、応答ライター w に HTML をレンダリングします。
func indexHandler(w http.ResponseWriter, r *http.Request) {
// Retrieve all notes from the database
notes, err := GetNotes()
if err != nil {
// Send an internal server error response if something goes wrong
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Parse the HTML template file
tmpl, err := template.ParseFiles("index.html")
if err != nil {
// Send an internal server error response if the template cannot be parsed
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Execute the template with the notes data
tmpl.Execute(w, notes)
}
機能: 追加ハンドラー
add ハンドラーは、メモがデータベースに追加されることを保証します。 ハンドラーには次の機能が含まれます。
リクエストメソッドを確認:POST リクエストのみが処理されることを保証します。
フォームの値を取得: フォームからタイトルとコンテンツの値を取得します。
メモの作成: CreateNote を呼び出して、データベースに新しいメモを追加します。
リダイレクト: メモを追加した後、ユーザーをホームページにリダイレクトします。
func addHandler(w http.ResponseWriter, r *http.Request) {
// Only handle POST requests
if r.Method == "POST" {
// Get the title and content from the form values
title := r.FormValue("title")
content := r.FormValue("content")
// Create a new note with the provided title and content
CreateNote(title, content)
}
// Redirect the user back to the homepage after adding the note
http.Redirect(w, r, "/", http.StatusSeeOther)
}
機能: 削除ハンドラー
削除ハンドラーは、データベースからメモを削除します。 このハンドラーは次の処理を実行します。
ID 変換: ID フォームの値を整数に変換します。 変換が失敗した場合は、不正な要求応答が送信されます。
メモの削除: DeleteNote を呼び出して、指定された ID のメモをデータベースから削除します。
リダイレクト: メモを削除した後、ユーザーをホームページにリダイレクトします。
func deleteHandler(w http.ResponseWriter, r *http.Request) {
// Convert the ID from the form value to an integer
id, err := strconv.Atoi(r.FormValue("id"))
if err != nil {
// Send a bad request response if the ID is not valid
http.Error(w, "Invalid ID", http.StatusBadRequest)
return
}
// Delete the note with the given ID
DeleteNote(id)
// Redirect the user back to the homepage after deleting the note
http.Redirect(w, r, "/", http.StatusSeeOther)
}
package main
import (
"html/template"
"log"
"net/http"
"strconv"
)
// main function is the entry point of the program
func main() {
// Initialize the database
initDB()
// Ensure the database connection is closed when the main function exits
defer db.Close()
// Set up HTTP handlers for different routes
http.HandleFunc("/", indexHandler) // Route for the homepage
http.HandleFunc("/add", addHandler) // Route for adding a new note
http.HandleFunc("/delete", deleteHandler) // Route for deleting a note
// Log the server start and listen on port 8080
log.Println("Server started at :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
// indexHandler handles the requests to the homepage
func indexHandler(w http.ResponseWriter, r *http.Request) {
// Retrieve all notes from the database
notes, err := GetNotes()
if err != nil {
// Send an internal server error response if something goes
// wrong
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Parse the HTML template file
tmpl, err := template.ParseFiles("index.html")
if err != nil {
// Send an internal server error response if the template
// cannot be parsed
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Execute the template with the notes data
tmpl.Execute(w, notes)
}
// addHandler handles the requests to add a new note
func addHandler(w http.ResponseWriter, r *http.Request) {
// Only handle POST requests
if r.Method == "POST" {
// Get the title and content from the form values
title := r.FormValue("title")
content := r.FormValue("content")
// Create a new note with the provided title and content
CreateNote(title, content)
}
// Redirect the user back to the homepage after adding the note
http.Redirect(w, r, "/", http.StatusSeeOther)
}
// deleteHandler handles the requests to delete a note
func deleteHandler(w http.ResponseWriter, r *http.Request) {
// Convert the ID from the form value to an integer
id, err := strconv.Atoi(r.FormValue("id"))
if err != nil {
// Send a bad request response if the ID is not valid
http.Error(w, "Invalid ID", http.StatusBadRequest)
return
}
// Delete the note with the given ID
DeleteNote(id)
// Redirect the user back to the homepage after deleting the note
http.Redirect(w, r, "/", http.StatusSeeOther)
}
次に、メモを追加および削除するためのフォームを含む index.html という新しいファイルを作成しましょう。 このファイルは html/template パッケージを使用します。 Go の html/template パッケージは、テンプレートを解析して実行する機能を提供します。 {{range .}} や {{.Title}} などのプレースホルダーは Go のテンプレート構文の一部であり、HTML に動的なコンテンツを挿入できます。
HTML テンプレートで使用される構文の詳細は次のとおりです。
{{range .}}: テンプレートに渡されたデータのコレクションに対してループを開始します。 この場合、 。 はテンプレートに渡されたデータ (Note 構造体のスライス) を表します。
{{range .}} はコレクション内の各要素を反復処理します。
{{.Title}}: {{range .}} ブロック内では、 。 は反復の現在の要素を参照します。 {{.Title}} は、現在の Note 構造体の タイトル フィールドにアクセスします。
{{else}}: 範囲がどの要素も反復処理しない場合 (たとえば、コレクションが空の場合) に表示する代替コンテンツを提供します。
{{end}}: 範囲ブロックの終了を示します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Notes App</title>
</head>
<body>
<h1>Notes</h1>
<form action="/add" method="post">
<label for="title">Title:</label>
<input type="text" id="title" name="title" required><br>
<label for="content">Content:</label>
<textarea id="content" name="content" required></textarea><br>
<button type="submit">Add Note</button>
</form>
<h2>Existing Notes</h2>
{{range .}}
<div>
<h3>{{.Title}}</h3>
<p>{{.Content}}</p>
<form action="/delete" method="post" style="display:inline;">
<input type="hidden" name="id" value="{{.ID}}">
<button type="submit">Delete</button>
</form>
</div>
{{else}}
<p>No notes available.</p>
{{end}}
</body>
</html>
Go コードとの接続
Go コードの indexHandler 関数では、データベースからメモを取得してテンプレートに渡します。
次のコードスニペットでは、 template.ParseFiles("index.html") が index.html ファイルを読み取って解析します。
tmpl.Execute(w, notes) はテンプレートを実行し、 notes をデータとして渡します。 この Note 構造体の notes スライスは、 {{range .}} が反復処理するものです。
// Parse the HTML template file
tmpl, err := template.ParseFiles("index.html")
if err != nil {
// Send an internal server error response if the template cannot be parsed
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Execute the template with the notes data
tmpl.Execute(w, notes)
ステップ 7: アプリケーションの実行
GoLand にはアプリケーションを実行するためのさまざまなオプションがあります。 最も簡単なのは、エディターから直接実行することです。
エディターから実行
プログラムにパラメーターを渡さず、開始前に特定のアクションが不要な場合は、エディターから直接実行できます。
生成された実行構成は、 go run . と同等の方法でパッケージを実行し、出力を 実行 ツールウィンドウに表示します。
次に、Web ブラウザーを開いて http://localhost:8080 に移動します。 メモを追加するためのフォームと、既存のメモのリストと、削除するオプションが表示されます。
2026 年 11 月 6 日