GOの基本的なMVC Webアプリケーション
このプロジェクトは、フレームワークなしでGO言語を使用してWebサイトを構築および構築する方法を示しています。 http://www.josephspurrier.com/go-web-app-example/で読むことができるブログ記事があります。 https://github.com/verifiedninja/webappにプロジェクトの以前のバージョンで構築された完全なアプリケーションがあります。 https://github.com/josephspurrier/gowebapiにこのプロジェクトのAPIバージョンがあります。
ダウンロードするには、次のコマンドを実行します。
go get github.com/josephspurrier/gowebapp
Go 1.5を使用している場合は、Govendorexperimentを1に設定する必要があります。1.4以前に行く場合は、ベンダーフォルダーを使用するため、コードは機能しません。
Gowebapp.dbファイルは、アプリケーションを開始すると作成されます。
ルートディレクトリからビルドして実行します。 Webブラウザを開きます:http:// localhost。ウェルカムページが表示されます。
ログインページに移動し、次に登録ページに移動します。新しいユーザーを作成すると、ログインできる必要があります。それでおしまい。
Mongodbを開始します。
config/config.jsonを開き、データベースセクションを編集して、接続情報がmongodbインスタンスと一致するようにします。また、タイプをボルトからモンゴドブに変更します。
ルートディレクトリからビルドして実行します。 Webブラウザを開きます:http:// localhost。ウェルカムページが表示されます。
ログインページに移動し、次に登録ページに移動します。新しいユーザーを作成すると、ログインできる必要があります。それでおしまい。
mysqlを起動し、config/mysql.sqlをインポートして、データベースとテーブルを作成します。
config/config.jsonを開き、データベースセクションを編集して、接続情報がmysqlインスタンスと一致するようにします。また、ボルトからmysqlにタイプを変更します。
ルートディレクトリからビルドして実行します。 Webブラウザを開きます:http:// localhost。ウェルカムページが表示されます。
ログインページに移動し、次に登録ページに移動します。新しいユーザーを作成すると、ログインできる必要があります。それでおしまい。
Webアプリには、パブリックホームページ、認証されたホームページ、ログインページ、登録ページ、ページについて、およびCRUD操作を実証する簡単なメモ帳があります。
WebアプリのエントリポイントはGowebapp.goです。ファイルはアプリケーションの設定を読み込み、セッションを開始し、データベースに接続し、テンプレートをセットアップし、ルートをロードし、ミドルウェアを接続し、Webサーバーを起動します。
フロントエンドは、フォントと間隔にいくつかの小さな変更を加えたブートストラップを使用して構築されています。フラッシュメッセージはカスタマイズされているため、画面の右下に表示されます。
すべてのエラーと警告メッセージは、ユーザーまたはコンソールに表示される必要があります。情報メッセージは、4秒後に消えるフラッシュメッセージを介してユーザーに表示されます。フラッシュメッセージは、静的フォルダーのJavaScriptによって制御されます。
最近、フォルダー構造が変更されました。すべてのフォークを見て、私のプロジェクトをさまざまな場所で再利用した後、私はGitHubパスが多くのインポートに散らばられないように、ベンダーフォルダー内のアプリフォルダーにGOコードを移動することにしました。相対パスを使用したくなかったので、ベンダーフォルダーは最良の選択肢のように見えました。
プロジェクトは次のフォルダーに編成されています。
config - application settings and database schema
static - location of statically served files like CSS and JS
template - HTML templates
vendor/app/controller - page logic organized by HTTP methods (GET, POST)
vendor/app/shared - packages for templates, MySQL, cryptography, sessions, and json
vendor/app/model - database queries
vendor/app/route - route information and middleware
いくつかの外部パッケージがあります:
github.com/gorilla/context - registry for global request variables
github.com/gorilla/sessions - cookie and filesystem sessions
github.com/go-sql-driver/mysql - MySQL driver
github.com/haisum/recaptcha - Google reCAPTCHA support
github.com/jmoiron/sqlx - MySQL general purpose extensions
github.com/josephspurrier/csrfbanana - CSRF protection for gorilla sessions
github.com/julienschmidt/httprouter - high performance HTTP request router
github.com/justinas/alice - middleware chaining
github.com/mattn/go-sqlite3 - SQLite driver
golang.org/x/crypto/bcrypt - password hashing algorithm
テンプレートは、テンプレートフォルダーの下のフォルダーに編成されています。
about/about.tmpl - quick info about the app
index/anon.tmpl - public home page
index/auth.tmpl - home page once you login
login/login.tmpl - login page
notepad/create.tmpl - create note
notepad/read.tmpl - read a note
notepad/update.tmpl - update a note
partial/footer.tmpl - footer
partial/menu.tmpl - menu at the top of all the pages
register/register.tmpl - register page
base.tmpl - base template for all the pages
テンプレートと静的ファイルを簡単に操作できるようにするために利用できるテンプレートファンがいくつかあります。
<!-- CSS files with timestamps -->
{{CSS "static/css/normalize3.0.0.min.css"}}
parses to
< link rel =" stylesheet " type =" text/css " href =" /static/css/normalize3.0.0.min.css?1435528339 " />
<!-- JS files with timestamps -->
{{JS "static/js/jquery1.11.0.min.js"}}
parses to
< script type =" text/javascript " src =" /static/js/jquery1.11.0.min.js?1435528404 " > </ script >
<!-- Hyperlinks -->
{{LINK "register" "Create a new account."}}
parses to
< a href =" /register " > Create a new account. </ a >
<!-- Output an unescaped variable (not a safe idea, but I find it useful when troubleshooting) -->
{{.SomeVariable | NOESCAPE}}
<!-- Time format -->
{{.SomeTime | PRETTYTIME}}
parses to format
3:04 PM 01/02/2006テンプレートでも使用できるいくつかの変数があります。
<!-- Use AuthLevel=auth to determine if a user is logged in (if session.Values["id"] != nil) -->
{{if eq .AuthLevel "auth"}}
You are logged in.
{{else}}
You are not logged in.
{{end}}
<!-- Use BaseURI to print the base URL of the web app -->
< li > < a href =" {{.BaseURI}}about " > About </ a > </ li >
<!-- Use token to output the CSRF token in a form -->
< input type =" hidden " name =" token " value =" {{.token}} " >また、閉じる前にテンプレート固有のコードを追加してタグを付けることも簡単です。
<!-- Code is added before the closing </head> tag -->
{{define "head"}} < meta name =" robots " content =" noindex " > {{end}}
...
<!-- Code is added before the closing </body> tag -->
{{define "foot"}}{{JS "//www.google.com/recaptcha/api.js"}}{{end}}JavaScriptを使用してフラッシュ通知をトリガーできます。
flashError ( "You must type in a username." ) ;
flashSuccess ( "Record created!" ) ;
flashNotice ( "There seems to be a piece missing." ) ;
flashWarning ( "Something does not seem right..." ) ; コントローラーファイルはすべて同じパッケージ名を共有します。これにより、ルートをマッピングするときにパッケージの数が削減されます。また、各ファンに優れた命名条約を使用することを余儀なくされているため、各ファンがどこにあるか、どのタイプのHTTPリクエストがマッピングされているかがわかります。
ゴリラセッションにアクセス:
// Get the current session
sess := session . Instance ( r )
...
// Close the session after you are finished making changes
sess . Save ( r , w )次のページのロードで4種類のフラッシュメッセージのうち1をトリガーします(他のコードは必要ありません):
sess . AddFlash (view. Flash { "Sorry, no brute force :-)" , view . FlashNotice })
sess . Save ( r , w ) // Ensure you save the session after making a change to itフォームフィールドの検証は空ではありません:
// Ensure a user submitted all the required form fields
if validate , missingField := view . Validate ( r , [] string { "email" , "password" }); ! validate {
sess . AddFlash (view. Flash { "Field missing: " + missingField , view . FlashError })
sess . Save ( r , w )
LoginGET ( w , r )
return
}テンプレートをレンダリングします:
// Create a new view
v := view . New ( r )
// Set the template name
v . Name = "login/login"
// Assign a variable that is accessible in the form
v . Vars [ "token" ] = csrfbanana . Token ( w , r , sess )
// Refill any form fields from a POST operation
view . Repopulate ([] string { "email" }, r . Form , v . Vars )
// Render the template
v . Render ( w )AJAXリクエスト中にフラッシュメッセージを返します。
// Get session
sess := session . Instance ( r )
// Set the flash message
sess . AddFlash (view. Flash { "An error occurred on the server. Please try again later." , view . FlashError })
sess . Save ( r , w )
// Display the flash messages as JSON
v := view . New ( r )
v . SendFlashes ( w )データベースクエリを処理します:
// Get database result
result , err := model . UserByEmail ( email )
if err == sql . ErrNoRows {
// User does not exist
} else if err != nil {
// Display error message
} else if passhash . MatchString ( result . Password , password ) {
// Password matches!
} else {
// Password does not match
}メールを送信する:
// Email a user
err := email . SendEmail ( email . ReadConfig (). From , "This is the subject" , "This is the body!" )
if err != nil {
log . Println ( err )
sess . AddFlash (view. Flash { "An error occurred on the server. Please try again later." , view . FlashError })
sess . Save ( r , w )
return
}Google Recaptchaが構成で有効になっている場合、フォームを検証します。
// Validate with Google reCAPTCHA
if ! recaptcha . Verified ( r ) {
sess . AddFlash (view. Flash { "reCAPTCHA invalid!" , view . FlashError })
sess . Save ( r , w )
RegisterGET ( w , r )
return
}データベースレイヤーを抽象化することをお勧めします。そのため、変更を加える必要がある場合は、クエリを見つけるためにビジネスロジックを調べる必要はありません。すべてのクエリはモデルフォルダーに保存されます。
このプロジェクトは、BoltdB、MongoDB、およびMySQLをサポートしています。すべてのクエリは同じファイルに保存されるため、構成ファイル以外のものを変更せずにデータベースを簡単に変更できます。
user.goおよびnote.goファイルはモデルディレクトリのrootにあり、各データベースタイプのすべてのクエリを補完します。モデルには、サポートされているすべてのデータベースで構造体を動作させるためのいくつかのハッキングがあります。
データベースに接続します(アプリケーションで1回だけ必要です):
// Connect to database
database . Connect ( config . Database )データベースから読む:
result := User {}
err := database . DB . Get ( & result , "SELECT id, password, status_id, first_name FROM user WHERE email = ? LIMIT 1" , email )
return result , errデータベースに書き込みます:
_ , err := database . DB . Exec ( "INSERT INTO user (first_name, last_name, email, password) VALUES (?,?,?,?)" , firstName , lastName , email , password )
return err ミドルウェアがいくつか含まれています。 CSRFBANANAと呼ばれるパッケージは、クロスサイトリクエストの偽造攻撃から保護し、二重の提出物を防ぎます。パッケージhttprouterwrapperは、httprouterと互換性のある微分を作成するためのヘルパー関数を提供します。パッケージLogRequestは、Webサイトに対して作成されたすべてのリクエストをコンソールにログに記録します。パッケージpprofhandlerはpprofを有効にして、httprouterで動作します。 Route.goでは、すべての個別のルートがアリスを使用してチェーンを非常に簡単にします。
Webアプリをもう少し柔軟にするために、Config.jsonファイルを介して1つの場所で異なるコンポーネントに変更を加えることができます。独自の設定を追加する場合は、それらをconfig.jsonに追加し、Gowebapp.goと個々のファイルの構造を更新して、コードで参照できるようにします。これはconfig.jsonです:
{
"Database" : {
"Type" : " Bolt " ,
"Bolt" : {
"Path" : " gowebapp.db "
},
"MongoDB" : {
"URL" : " 127.0.0.1 " ,
"Database" : " gowebapp "
},
"MySQL" : {
"Username" : " root " ,
"Password" : " " ,
"Name" : " gowebapp " ,
"Hostname" : " 127.0.0.1 " ,
"Port" : 3306 ,
"Parameter" : " ?parseTime=true "
}
},
"Email" : {
"Username" : " " ,
"Password" : " " ,
"Hostname" : " " ,
"Port" : 25 ,
"From" : " "
},
"Recaptcha" : {
"Enabled" : false ,
"Secret" : " " ,
"SiteKey" : " "
},
"Server" : {
"Hostname" : " " ,
"UseHTTP" : true ,
"UseHTTPS" : false ,
"HTTPPort" : 80 ,
"HTTPSPort" : 443 ,
"CertFile" : " tls/server.crt " ,
"KeyFile" : " tls/server.key "
},
"Session" : {
"SecretKey" : " @r4B?EThaSEh_drudR7P_hub=s#s2Pah " ,
"Name" : " gosess " ,
"Options" : {
"Path" : " / " ,
"Domain" : " " ,
"MaxAge" : 28800 ,
"Secure" : false ,
"HttpOnly" : true
}
},
"Template" : {
"Root" : " base " ,
"Children" : [
" partial/menu " ,
" partial/footer "
]
},
"View" : {
"BaseURI" : " / " ,
"Extension" : " tmpl " ,
"Folder" : " template " ,
"Name" : " blank " ,
"Caching" : true
}
}httpsを有効にするには、usehttpsをtrueに設定し、ルートにtlsというフォルダーを作成し、そのフォルダーに証明書とキーファイルを配置します。
公共の家:
について:
登録する:
ログイン:
認証された家:
メモを見る:
追加メモ:
編集注:
すべてのフィードバックは大歓迎です。提案、質問、または批判があるかどうかを教えてください。何かが慣用的でない場合は、私たちがそれを改善できるように私に知らせてください。