0
1

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言語(Golang)における簡単なWEBサーバーの構築

Last updated at Posted at 2024-10-15
package main

import (
	"errors"
	"fmt"
	"net/http"
)

func LogOutput(message string) {
	fmt.Println(message)

}

type SimpleDataStore struct {
	userData map[string]string
}

func (sds SimpleDataStore) UserNameForID(userID string) (string, bool) {
	name, ok := sds.userData[userID]
	return name, ok
}

func NewSimpleDataStore() SimpleDataStore {
	return SimpleDataStore{
		userData: map[string]string{
			"1": "Fred",
			"2": "Mary",
			"3": "Pat",
		},
	}
}

type DataStore interface {
	UserNameForID(userID string) (string, bool)
}

type Logger interface {
	Log(message string)
}

type LoggerAdapter func(message string)

func (lg LoggerAdapter) Log(message string) {
	lg(message)
}

type SimpleLogic struct {
	l  Logger
	ds DataStore
}

func (sl SimpleLogic) SayHello(userID string) (string, error) {
	sl.l.Log("SayHello(" + userID + ")")
	name, ok := sl.ds.UserNameForID(userID)
	if !ok {
		return "", errors.New("不明なユーザー")
	}
	return name + "さん、こんにちは。", nil
}

func (sl SimpleLogic) SayGoodbye(userID string) (string, error) {
	sl.l.Log("SayGoodbye(" + userID + ")")
	name, ok := sl.ds.UserNameForID(userID)
	if !ok {
		return "", errors.New("不明なユーザー")
	}
	return name + "さんさようなら。", nil
}

func NewSimpleLogic(l Logger, ds DataStore) SimpleLogic {
	return SimpleLogic{
		l:  l,
		ds: ds,
	}
}

type Logic interface {
	SayHello(userID string) (string, error)
}

type Controller struct {
	l     Logger
	logic Logic
}

func (c Controller) SayHello(w http.ResponseWriter, r *http.Request) {
	c.l.Log("SayHello内: ")
	userID := r.URL.Query().Get("user_id")
	message, err := c.logic.SayHello(userID)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte(err.Error()))
		return
	}
	w.Write([]byte(message))
}

func NewController(l Logger, logic Logic) Controller {
	return Controller{
		l:     l,
		logic: logic,
	}
}

func main() {
	l := LoggerAdapter(LogOutput)
	ds := NewSimpleDataStore()
	logic := NewSimpleLogic(l, ds)
	c := NewController(l, logic)
	http.HandleFunc("/hello", c.SayHello)
	http.ListenAndServe(":8080", nil)
}

func LogOutput(message string) {
	fmt.Println(message)
}
  • LogOutput関数を定義します。この関数は、引数として受け取ったメッセージをコンソールに出力します。
type SimpleDataStore struct {
    userData map[string]string
}
  • SimpleDataStoreという構造体を定義します。この構造体は、ユーザーIDと名前のペアを保持するためのuserDataというマップを持っています。
func (sds SimpleDataStore) UserNameForID(userID string) (string, bool) {
    name, ok := sds.userData[userID]
    return name, ok
}
  • UserNameForIDメソッドを定義します。このメソッドは、ユーザーIDを引数に取り、そのIDに対応する名前を検索します。見つかった場合は名前とtrueを、見つからなかった場合は空文字列とfalseを返します。
func NewSimpleDataStore() SimpleDataStore {
    return SimpleDataStore{
        userData: map[string]string{
            "1": "Fred",
            "2": "Mary",
            "3": "Pat",
        },
    }
}
  • NewSimpleDataStore関数を定義します。この関数は、初期化されたSimpleDataStoreを返します。ここでは、ユーザーIDと名前のマッピングが設定されています。
type DataStore interface {
    UserNameForID(userID string) (string, bool)
}
  • DataStoreインターフェースを定義します。このインターフェースは、UserNameForIDメソッドを要求します。これは、IDに基づいて名前を取得する機能を持つことを示しています。
type Logger interface {
    Log(message string)
}
  • Loggerインターフェースを定義します。このインターフェースは、ログメッセージを出力するためのLogメソッドを要求します。
type LoggerAdapter func(message string)
  • LoggerAdapterという関数型を定義します。この型は、Logメソッドを持つインターフェースに対応させるために使用されます。
func (lg LoggerAdapter) Log(message string) {
    lg(message)
}
  • LoggerAdapterLogメソッドを実装します。このメソッドは、受け取ったメッセージを関数として呼び出します。これにより、適応された関数がロギング機能を持つことができます。
type SimpleLogic struct {
    l  Logger
    ds DataStore
}
  • SimpleLogicという構造体を定義します。この構造体は、ロギング機能(l)とデータストア(ds)を持ちます。これにより、ビジネスロジックを実装する際に両方を使用できます。
func (sl SimpleLogic) SayHello(userID string) (string, error) {
    sl.l.Log("SayHello(" + userID + ")")
    name, ok := sl.ds.UserNameForID(userID)
    if !ok {
        return "", errors.New("不明なユーザー")
    }
    return name + "さん、こんにちは。", nil
}
  • SayHelloメソッドを定義します。このメソッドは、ユーザーIDを引数に取り、挨拶メッセージを生成します。
    • 最初に、SayHelloが呼ばれたことをログに記録します。
    • 次に、データストアからユーザー名を取得します。
    • ユーザーが見つからない場合は、エラーを返します。
    • ユーザーが見つかれば、挨拶メッセージを返します。
func (sl SimpleLogic) SayGoodbye(userID string) (string, error) {
    sl.l.Log("SayGoodbye(" + userID + ")")
    name, ok := sl.ds.UserNameForID(userID)
    if !ok {
        return "", errors.New("不明なユーザー")
    }
    return name + "さんさようなら。", nil
}
  • SayGoodbyeメソッドもSayHelloと同様の構造ですが、さようならメッセージを生成します。
func NewSimpleLogic(l Logger, ds DataStore) SimpleLogic {
    return SimpleLogic{
        l:    l,
        ds: ds,
    }
}
  • NewSimpleLogic関数を定義します。この関数は、ロガー(l)とデータストア(ds)を受け取り、初期化されたSimpleLogicを返します。
type Logic interface {
    SayHello(userID string) (string, error)
}
  • Logicインターフェースを定義します。このインターフェースは、SayHelloメソッドを要求します。これは、ユーザーIDに基づいて挨拶を行うロジックを持つことを示しています。
type Controller struct {
    l     Logger
    logic Logic
}
  • Controller構造体を定義します。この構造体は、ロギング機能(l)とビジネスロジック(logic)を持ちます。HTTPリクエストを処理する役割を持っています。
func (c Controller) SayHello(w http.ResponseWriter, r *http.Request) {
    c.l.Log("SayHello内: ")
    userID := r.URL.Query().Get("user_id")
    message, err := c.logic.SayHello(userID)
    if err != nil {
        w.WriteHeader(http.StatusBadRequest)
        w.Write([]byte(err.Error()))
        return
    }
    w.Write([]byte(message))
}
  • SayHelloメソッドを定義します。このメソッドは、HTTPリクエストを処理し、クエリパラメータからuser_idを取得します。
    • 最初に、SayHello内でログを記録します。
    • 次に、ユーザーIDを用いてビジネスロジックのSayHelloメソッドを呼び出します。
    • エラーが発生した場合は、HTTPステータスコード400(不正なリクエスト)を返し、エラーメッセージを表示します。
    • エラーがなければ、生成されたメッセージをHTTPレスポンスとして返します。
func NewController(l Logger, logic Logic) Controller {
    return Controller{
        l:     l,
        logic: logic,
    }
}
  • NewController関数を定義します。この関数は、ロガー(l)とロジック(logic)を受け取り、初期化されたControllerを返します。
func main() {
    l := LoggerAdapter(LogOutput)
    ds := NewSimpleDataStore()
    logic := NewSimpleLogic(l, ds)
    c := NewController(l, logic)
    http.HandleFunc("/hello", c.SayHello)
    http.ListenAndServe(":8080", nil)
}
  • main関数は、プログラムのエントリーポイントです。
    • 最初に、LogOutput関数をLoggerAdapterとしてラップします。
    • 次に、NewSimpleDataStoreを呼び出してデータストアを初期化します。
    • その後、NewSimpleLogicを使ってビジネスロジックを初期化します。
    • NewControllerを使ってコントローラーを初期化します。
    • http.HandleFuncを使って、/helloエンドポイントへのリクエストをSayHelloメソッドにマッピングします。
    • 最後に、http.ListenAndServeを使って、ポート8080でHTTPサーバーを起動します。

ブラウザで次のURLを表示してみてください(user_id= のあとに1, 2, 3などを指定)

0
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?