0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Go言語】WebフレームワークEchoとent.を連携する方法(PostgreSQL使用)

Last updated at Posted at 2025-02-16

今回は、Webフレームワーク①Echoと②Ent.を使って簡単なWebアプリを作ってみます。

こちらの記事を参考にしました↓

Echo公式サイト

ent.公式サイト

今回の記事では少し変更を加えています。

ディレクトリ構成

MYECHO
├─ ent
│  ├─ entry
│  ├─ enttest
│  ├─ hook
│  ├─ migrate
│  ├─ prodicate
│  ├─ runtime
│  ├─ schema
│  │  └─ entry.go
│  ├─ client.go
│  ├─ ent.go
│  ├─ entry_create.go
│  ├─ entry_delete.go
│  ├─ entry_query.go
│  ├─ entry_update.go
│  ├─ entry.go
│  ├─ ganerate.go
│  ├─ mutation.go
│  ├─ runtime.go
│  └─ tx.go
├─ templates
│  └─ index.htm
├─ go.mod
├─ go.sum
└─ main.go

サンプル

http://localhost:8989/にアクセスしてタスク投稿画面を起動します。
ent画面起動.png

タスクを入力します。
ent投稿内容入力.png

タスクが無事登録されると、下記のキャプチャのように登録内容が表示されます。
ent投稿内容結果.png

変更点

■CSSファイルを読み込む設定を追加
■CSSフレームワークBootstrapを使用
■PostgreSQLを使用

Echoプロジェクトを作成する

【手順】

■デスクトップにプロジェクトフォルダを作る

mkdir <プロジェクト名>

(例)
mkdir myEcho

■Echo公式サイトの通りモジュールを初期化する。

go mod init <モジュール名>

(例)
go mod init myapp

■Echo公式さとでEchoプロジェクトに必要なソースをインストールする。

go get github.com/labstack/echo/v4

■Echoプロジェクト直下に「main.go」を追加する

■プロジェクトフォルダ(例:myEchoフォルダ)に移動して、entスキーマを作成する。

go run -mod=mod entgo.io/ent/cmd/ent new <スキーマ名>
(例)
go run -mod=mod entgo.io/ent/cmd/ent new Entry

■スキーマを定義する。

ent/schema/entry.go
package schema

import (
	"time"

	"entgo.io/ent"
	"entgo.io/ent/schema/field"
)

// Entry holds the schema definition for the Entry entity.
type Entry struct {
	ent.Schema
}

// Fields of the Entry.
func (Entry) Fields() []ent.Field { //←の関数を修正する
	return []ent.Field{
		field.String("content").Default(""),
		field.Time("created_at").Default(func() time.Time { return time.Now() }),
	}
}

// Edges of the Entry.
func (Entry) Edges() []ent.Edge {
	return nil
}

■修正したスキーマをもとにクラスを自動酢生成する。

go generate ./ent

すると、下記のようにフォルダが自動で生成される。

スキーマ.png

PostgreSQLドライバをインストールする。

go get github.com/lib/pq

■モジュールの依存関係を解消する。

go mod tidy

Echoの最新モジュールをインストールする。

go get github.com/labstack/echo/v4

main.goを修正する。

main.go
package main

import (
	"context"
	"html/template"
	"io"
	"log"
	"myapp/ent"
	"myapp/ent/entry"
	"net/http"

	"github.com/labstack/echo/v4"
	_ "github.com/lib/pq"
)

// CustomRenderer is a custom renderer for HTML templates.
type CustomRenderer struct {
	templates *template.Template
}

// NewCustomRenderer creates a new CustomRenderer.
func NewCustomRenderer() *CustomRenderer {
	// Load all templates from the templates directory
	tmpl, err := template.ParseFiles("templates/index.html")
	if err != nil {
		log.Fatal("Error loading template:", err)
	}
	return &CustomRenderer{templates: tmpl}
}

// Render renders the template with the given name and data.
func (cr *CustomRenderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
	// Render the template to the provided io.Writer (which is http.ResponseWriter)
	return cr.templates.ExecuteTemplate(w, name, data)
}

func main() {
	client, err := ent.Open("postgres", "host=<ホスト名> port=5432 user=<ユーザ名> dbname=<データベース名> password=<パスワード> sslmode=disable")
	if err != nil {
		log.Fatalf("failed opening connection to postgres: %v", err)
	}
	defer client.Close()

	// Run the auto migration tool.
	if err := client.Schema.Create(context.Background()); err != nil {
		log.Fatalf("failed creating schema resources: %v", err)
	}

	e := echo.New()

	// Set the custom renderer for rendering HTML templates
	e.Renderer = NewCustomRenderer()
	//スタイリングシートCSS読み込み設定
	e.Static("/css", "src/css")
	//Bootstrap読み込み設定
	e.Static("/bootstrap/css", "src/lib/bootstrap/css")

	e.GET("/", func(c echo.Context) error {
		// Fetch the 10 most recent entries
		eq := client.Entry.Query().Order(ent.Desc(entry.FieldCreatedAt)).Limit(10)
		entries, err := eq.All(context.Background())
		if err != nil {
			log.Println("Error fetching entries:", err)
			return c.String(http.StatusInternalServerError, "Failed to load entries")
		}
		// Render the index.html template with the entries
		return c.Render(http.StatusOK, "index.html", map[string]interface{}{
			"entries": entries,
		})
	})

	e.POST("/add", func(c echo.Context) error {
		e := client.Entry.Create()
		e.SetContent(c.FormValue("content"))
		if _, err := e.Save(context.Background()); err != nil {
			log.Println(err.Error())
			return c.String(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
		}
		return c.Redirect(http.StatusFound, "/")
	})

	e.Logger.Fatal(e.Start(":8989"))
}

エラー「failed creating schema resources: querying server version pq: SSL is not enabled on the server」が出た場合の対処方法

このエラーは、PostgreSQLサーバーがSSL接続を要求しているにもかかわらず、entライブラリでSSLが無効の設定で接続しようとしているため発生しています。
エラーメッセージによれば、「SSLが有効でないサーバーに接続しようとしている」とあります。

解決方法

SSLを無効にする: PostgreSQLサーバーがSSLを要求していない場合でも、接続文字列の中にSSLを無効にする設定を追加することで解決できます。

SSLを有効にする: PostgreSQLサーバーがSSLを要求している場合、entライブラリで接続時にSSLを有効にする必要があります。

1. SSL無効にする場合

接続文字列にsslmode=disableを追加して、SSLを無効にすることができます。以下のように修正します。

main.go
client, err := ent.Open("postgres", "host=<ホスト名> port=5432 user=<ユーザ名> dbname=<データベース名> password=<パスワード> sslmode=disable")

2. SSL有効にする場合

PostgreSQLサーバーがSSL接続を要求している場合、接続文字列に適切なSSLオプションを追加する必要があります。例えば、sslmode=requireを指定します。

maio.go
client, err := ent.Open("postgres", "host=<ホスト名> port=5432 user=<ユーザ名> dbname=<データベース名> password=<パスワード> sslmode=require")

テンプレートエンジンhtmlを使用する場合

GoのEchoフレームワークでHTMLテンプレートをレンダリングするためには、echo.Rendererインターフェースを実装する必要があります。

以下の手順で修正できます:

テンプレートレンダラーの作成: Echoフレームワークでは、HTMLテンプレートをレンダリングするために、echo.Rendererインターフェースを実装したカスタムレンダラーを作成する必要があります。

テンプレートファイルのレンダリング: Echoフレームワークはhtml/templateを使ってテンプレートをレンダリングできます。t.Executeの代わりに、c.Renderメソッドを使ってレンダリングします。

使用する関数としてはRender(w io.Writer, name string, data interface{}, c echo.Context)を使用してレンダリングを行います。

c.Renderで渡すテンプレート名は、ファイル名(拡張子なし)で指定します。templates/index.htmlを指定している部分を、ファイル名index.htmlを渡すようにします。

■Echoプロジェクトを起動する。

go run main.go

そうすると、PostgreSQLのテーブルにスキーマが反映されます。

スタイリングシートの読み込み

CSSやBootstrap,Javascriptなどのファイルを読み込んでみましょう。

main.go
//スタイリングシートCSS読み込み設定
e.Static("/css", "src/css")

//Bootstrap読み込み設定
e.Static("/bootstrap/css", "src/lib/bootstrap/css")

第一引数に省略した形のパスを、第二引数に相対パスを記載します。

つぎにHTMLファイルでは下記のように記載します。
hrefの部分は、前述の関数(e.Static("第一引数","第二引数"))の第一引数と読み込むファイル名を記載します。

templates/index.html
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"/>
<link rel="stylesheet" href="css/index.css"/>

全体のコードはこちら↓

templates/index.html
<!DOCTYPE html>
<html>
    <head>
        <title>タイトル</title>
        <!--共通-->
        <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"/>
        <!--個別ファイル-->
        <link rel="stylesheet" href="css/index.css"/>
    </head>
    <body>
        <h1>投稿内容</h1>
        <form method="post" action="/add">
            <label for="exampleInputEmail1" class="form-label">登録するタスク</label>
            <input type="text" name="content" class="form-control border border-primary" required/>
            <input type="submit" value="送信" class="btn btn-primary"/>
        </form>
        <ul>
            {{range .entries}}
                <li>{{.Content}}</li>
            {{else}}
                <li>まだ投稿はありません。</li>
            {{end}}
        </ul>
    </body>
</html>

以上です。

参考にしたサイト

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?