- 投稿日:2020-03-31T16:05:59+09:00
(Go言語)WebAssemblyで簡単なWebサイトを作ってみた
前書き
Go言語の勉強を進める中でWebAssemblyが気になったので試してみました。
いろいろな情報尾参考にしつつ勉強中なので、間違い等ありましたらコメントをお願い致します。
ファイル 【Githab】目次
・WebAssemblyとは
・実行環境
・ディレクトリ構成と各ファイルについて
・簡易電卓の実装
・感想WebAssemblyとは
モダンなブラウザにおいて、
スクリプトファイルをアセンブリ言語に変換したうえで読み込み実行する仕組みのこと実行環境
OS:Windows 10 64bit
言語環境:go version go1.14.1
ブラウザ:Firefox バージョン: 74.0ディレクトリ構成と各ファイルについて 【Githab】
「main.go」はあくまでソースファイルなので実行する際にディレクトリに置いておく必要はありません
「server.go」に関してもテスト用なので別途webサーバが稼働しているなら必要ありません。ディレクトリ構成calc |-index.html(アクセスするhtmlファイル) |-main.go(WebAssemblyのソースファイル) |-wain.wasm(上記をコンパイルしたファイル) |-server.go(テスト用の簡易Webサーバ) |-wasm_exec.js(実行に必要なスクリプトファイル)簡易電卓の実装
1.WebAssemblyファイルの作成
まずgo言語でプログラムを記述しそれをWebAssembly形式にコンパイルします。
(go言語のソースファイルは割愛)コマンドプロンプト..\calc> set set GOOS=js ..\calc> set GOARCH=wasm ..\calc> go build -o main.wasm main.goWebAssembly形式でコンパイルすると「main.wasm」が生成されます。
あとは、「server.go」を実行しブラウザ経由でアクセスすることでアクセスできます。
感想
一部Javascriptを併用する部分があり完全にgo言語のみで動的Webサイトの実装は難しいと思いました。
学習コストを抑えるためできる限りGo言語でWebシステムを実装できる様に勉強中ですが、Javascriptの知識も得るか、何らかのフレームワークを使用する必要があると感じました。次はGoのフレームワークで多機能なサイトが作れないか調べていこうと思います。
- 投稿日:2020-03-31T05:54:33+09:00
Golangで、デザインパターン「State」を学ぶ
GoFのデザインパターンをGolangで学習してみたいと思います。
今回は、Qiita記事: "Pythonで、デザインパターン「State」を学ぶ"で取り上げた、Pythonベースの”State”のサンプルアプリをGolangで実装し直してみました。■ State(ステート・パターン)
Stateパターンとは、プログラミングで用いられる振る舞いに関する(英語版) デザインパターンの一種である。このパターンはオブジェクトの状態(state)を表現するために用いられる。ランタイムでそのタイプを部分的に変化させるオブジェクトを扱うクリーンな手段となる。
UML class and sequence diagram
UML class diagram
□ 備忘録
State
パターンでは、「状態」という物をクラスで表現するそうです。
状態に依存した振る舞いをここのConcreteState
役に分担させることが可能になります。
ただ、State
パターンを使う場合、状態遷移を誰が管理すべきかという点には注意が必要です。
(状態遷移をConcreteState
役に任せてしまうとクラス間の依存関係を深めてしまいます。)■ "State"のサンプルプログラム
実際に、Stateパターンを活用したサンプルプログラムを動かしてみて、次のような動作の様子を確認したいと思います。ここでは、"パソコン操作による起動状態の可視化"をイメージしてください。
- パソコンを起動すると、動作状態は、"running"になる
- パソコンを停止すると、動作状態が、"shutdown"になる
- パソコンを再起動すると、動作状態が、"running"になる
なお、サンプルプログラムでは、第一引数:最初のパソコン操作、第二引数:二度目のパソコン操作を指定します。
(事例1) パソコンを起動して、停止する
動作状態は、最初、パソコンに起動よって、"running"になって、その後、パソコンの停止によって、"shutdown"になります。
$ go run Main.go start stop ### パソコンを、[start]します *** パソコンは、起動中です ### パソコンは、[running]の動作状態になりました ... sleep 5 second ### パソコンを、[stop]します *** パソコンは、停止しています ### パソコンの動作状態は、[shutdown]になりました(事例2) パソコンを起動して、再起動する
動作状態は、最初、パソコンに起動よって、"running"になって、その後、パソコンの再起動によって、再び、"running"になります。
$ go run Main.go start restart ### パソコンを、[start]します *** パソコンは、起動中です ### パソコンは、[running]の動作状態になりました ... sleep 5 second ### パソコンを、[restart]します *** パソコンは、再起動をはじめます *** パソコンは、起動中です ### パソコンの動作状態は、[running]になりました以上で、想定どおり、サンプリプログラムが動作しました。
■ サンプルプログラムの詳細
Gitリポジトリにも、同様のコードをアップしています。
https://github.com/ttsubo/study_of_design_pattern_with_golang/tree/master/State
- ディレクトリ構成
. ├── Main.go └── state ├── context.go └── state.go(1) State(状態)の役
State
役は、状態を表すためのものです。状態ごとに異なる振る舞いをするインタフェースを定めます。
サンプルプログラムでは、State
インタフェースが、この役を努めます。state/state.gopackage state import "fmt" // State is interface type State interface { handle(context *Context) getConcreateState() string }(2) ConcreteState(具体的な状態)の役
ConcreteState
役は、具体的な個々の状態を表現するものです。
State
役で定められたインタフェースを具体的に実装します。
サンプルプログラムでは、
ConcreteStateBooting
構造体ConcreteStateRun
構造体ConcreteStateShutDown
構造体ConcreteStateRestart
構造体が、この役を努めます。
state/state.gotype concreteState struct { state string } func (c *concreteState) getConcreateState() string { return c.state }state/state.go// ConcreteStateBooting is struct type ConcreteStateBooting struct { *concreteState } // NewConcreteStateBooting func for initializing ConcreteStateBooting func NewConcreteStateBooting(state string) *ConcreteStateBooting { return &ConcreteStateBooting{ concreteState: &concreteState{ state: state, }, } } func (c *ConcreteStateBooting) handle(context *Context) { fmt.Println("*** パソコンは、起動中です") context.SetState(NewConcreteStateRun("running")) }state/state.go// ConcreteStateRun is struct type ConcreteStateRun struct { *concreteState } // NewConcreteStateRun func for initializing ConcreteStateRun func NewConcreteStateRun(state string) *ConcreteStateRun { return &ConcreteStateRun{ concreteState: &concreteState{ state: state, }, } } func (c *ConcreteStateRun) handle(context *Context) { fmt.Println("*** パソコンは、動作中です") }state/state.go// ConcreteStateShutDown is struct type ConcreteStateShutDown struct { *concreteState } // NewConcreteStateShutDown func for initializing ConcreteStateShutDown func NewConcreteStateShutDown(state string) *ConcreteStateShutDown { return &ConcreteStateShutDown{ concreteState: &concreteState{ state: state, }, } } func (c *ConcreteStateShutDown) handle(context *Context) { fmt.Println("*** パソコンは、停止しています") }state/state.go// ConcreteStateRestart is struct type ConcreteStateRestart struct { *concreteState } // NewConcreteStateRestart func for initializing ConcreteStateRestart func NewConcreteStateRestart(state string) *ConcreteStateRestart { return &ConcreteStateRestart{ concreteState: &concreteState{ state: state, }, } } func (c *ConcreteStateRestart) handle(context *Context) { fmt.Println("*** パソコンは、再起動をはじめます") context.SetState(NewConcreteStateBooting("booting")) context.Handle() }(3) Context(状態、前後関係、文脈)の役
Context
役は、現在の状態を表すConcreteState
役のオブジェクトを保持します。
サンプルプログラムでは、Context
構造体が、この役を努めます。state/context.gopackage state // Context is struct type Context struct { state State } // NewContext func for initializing Context func NewContext(stateObj State) *Context { return &Context{ state: stateObj, } } // SetState func for change state func (c *Context) SetState(obj State) { c.state = obj } // Handle func for handling state func (c *Context) Handle() { c.state.handle(c) } // GetState func for fetching state func (c *Context) GetState() string { return c.state.getConcreateState() }(4) Client(依頼人)の役
サンプルプログラムでは、
startMain
関数が、この役を努めます。Main.gopackage main import ( "flag" "fmt" "time" "./state" ) func setConcreteState(operation string) state.State { var stateObj state.State if operation == "start" { stateObj = state.NewConcreteStateBooting("booting") } else if operation == "stop" { stateObj = state.NewConcreteStateShutDown("shutdown") } else if operation == "restart" { stateObj = state.NewConcreteStateRestart("restart") } return stateObj } func startMain(initialOperation, changeOperation string) { obj := state.NewContext(setConcreteState(initialOperation)) fmt.Printf("### パソコンを、[%s]します\n", initialOperation) obj.Handle() fmt.Printf("### パソコンは、[%s]の動作状態になりました\n", obj.GetState()) fmt.Println("") fmt.Println("... sleep 5 second") fmt.Println("") time.Sleep(time.Second * 5) obj.SetState(setConcreteState(changeOperation)) fmt.Printf("### パソコンを、[%s]します\n", changeOperation) obj.Handle() fmt.Printf("### パソコンの動作状態は、[%s]になりました\n", obj.GetState()) } func main() { flag.Parse() startMain(flag.Arg(0), flag.Arg(1)) }■ 参考URL
- 投稿日:2020-03-31T05:36:20+09:00
Golangで、デザインパターン「Observer」を学ぶ
GoFのデザインパターンを学習する素材として、書籍「増補改訂版Java言語で学ぶデザインパターン入門」が参考になるみたいですね。
取り上げられている実例は、JAVAベースのため、Pythonで同等のプラクティスに挑んだことがありました。
Qiita記事: "Pythonで、デザインパターン「Observer」を学ぶ"今回は、Pythonで実装した”Observer”のサンプルアプリをGolangで実装し直してみました。
■ Observerパターン(オブザーバ・パターン)
Observerパターンとは、プログラム内のオブジェクトのイベント( 事象 )を他のオブジェクトへ通知する処理で使われるデザインパターンの一種。
通知するオブジェクト側が、通知されるオブジェクト側に観察(英: observe)される形になる事から、こう呼ばれる。
出版-購読型モデルとも呼ばれる。暗黙的呼び出しの原則と関係が深い。
分散イベント処理システムの実装にも使われる。言語によっては、このパターンで扱われる問題は言語が持つイベント処理構文で処理される。UML class and sequence diagram
UML class diagram
□ 備忘録
Observer
パターンでは、観察対象の状態が変化すると、観察者に対して通知されるので、状態変化に応じた処理を記述するときに有効だそうです。
observer
という言葉の本来の意味は「観察者」ですが、実際には、Observer
役は能動的に「観察」するのではなく、Subject
役から「通知」されるのを受動的に待っていることになるので、Publish-Subscribe
パターンと呼ばれることもあるそうです。
確かに、publish(発行)
とsubscribe(購読)
という表現の方が、適切のような気がしました。■ "Observer"のサンプルプログラム
実際に、Observerパターンを活用したサンプルプログラムを動かしてみて、次のような動作の様子を確認したいと思います。
- 数をたくさん生成するオブジェクトを観察者が観察して、その値を表示する仕組みになります
- 表示の方法は、観察者によって異なります。
DigitalObserver
は、値を数字で表示しますGraphicObserver
は、値を簡易グラフで表示します$ go run Main.go DigitObservser: 10 GraphicObserver:********** DigitObservser: 18 GraphicObserver:****************** DigitObservser: 14 GraphicObserver:************** DigitObservser: 28 GraphicObserver:**************************** DigitObservser: 22 GraphicObserver:********************** DigitObservser: 45 GraphicObserver:********************************************* DigitObservser: 38 GraphicObserver:************************************** DigitObservser: 37 GraphicObserver:************************************* DigitObservser: 30 GraphicObserver:****************************** DigitObservser: 9 GraphicObserver:********* DigitObservser: 9 GraphicObserver:********* DigitObservser: 46 GraphicObserver:********************************************** DigitObservser: 21 GraphicObserver:********************* DigitObservser: 2 GraphicObserver:** DigitObservser: 36 GraphicObserver:************************************ DigitObservser: 31 GraphicObserver:******************************* DigitObservser: 4 GraphicObserver:**** DigitObservser: 27 GraphicObserver:*************************** DigitObservser: 33 GraphicObserver:********************************* DigitObservser: 25 GraphicObserver:*************************■ サンプルプログラムの詳細
Gitリポジトリにも、同様のコードをアップしています。
https://github.com/ttsubo/study_of_design_pattern_with_golang/tree/master/Observer
- ディレクトリ構成
. ├── Main.go └── observer ├── generator.go └── observer.go(1) Subject(被験者)の役
Subject
役は、「観察される側」を表します。Subject
役は、観察者であるObserver
役を登録するメソッドと、削除するメソッドを持っています。また、「現在の状態を取得する」メソッドも宣言されています。
サンプルプログラムでは、NumberGenerator
構造体が、この役を努めます。observer/generator.gopackage observer import ( "math/rand" "time" ) // NumberGenerator is struct type NumberGenerator struct { number int observers []Observer } // AddObserver func for adding Observer func (n *NumberGenerator) AddObserver(observer Observer) { n.observers = append(n.observers, observer) } func (n *NumberGenerator) notifyObserver() { for _, o := range n.observers { o.update(n) } } func (n *NumberGenerator) getNumber() int { return n.number }(2) ConcreteSubject(具体的な被験者)の役
ConcreteSubject
役は、具体的な「観察される側」を表現する役です。状態が変化したら、そのことを登録されているObserver
役に伝えます。
サンプルプログラムでは、RandomNumberGenerator
構造体が、この役を努めます。observer/generator.go// RandomNumberGenerator is struct type RandomNumberGenerator struct { *NumberGenerator } // NewRandomNumberGenerator func for initializing RandomNumberGenerator func NewRandomNumberGenerator() *RandomNumberGenerator { return &RandomNumberGenerator{ NumberGenerator: &NumberGenerator{number: 0}, } } // Execute func for executing something func (r *RandomNumberGenerator) Execute() { for i := 0; i < 20; i++ { rand.Seed(time.Now().UnixNano()) r.number = rand.Intn(49) r.notifyObserver() } }(3) Observer(観察者)の役
Observer
役は、Subject
役から「状態が変化しましたよ」と教えてもらう役です。そのためのメソッドがupdate
です。
サンプルプログラムでは、Observer
インタフェースが、この役を努めます。observer/observer.gopackage observer import ( "fmt" "time" ) // Observer is interface type Observer interface { update(generator *NumberGenerator) }(4) ConcreteObserver(具体的な観察者)の役
ConcreteObserver
役は、具体的なObserver
です。update
メソッドが呼び出されると、そのメソッドの中でSubject
役の現在の状態を取得します。
サンプルプログラムでは、DigitObserver
構造体とGraphObserver
構造体が、この役を努めます。observer/observer.go// DigitObserver is struct type DigitObserver struct { } // NewDigitObserver func for initializing DigitObserver func NewDigitObserver() *DigitObserver { return &DigitObserver{} } func (d *DigitObserver) update(generator *NumberGenerator) { fmt.Printf("DigitObservser: %d\n", generator.getNumber()) time.Sleep(time.Millisecond * 100) }observer/observer.go// GraphObserver is struct type GraphObserver struct { } // NewGraphObserver func for initializing GraphObserver func NewGraphObserver() *GraphObserver { return &GraphObserver{} } func (g *GraphObserver) update(generator *NumberGenerator) { fmt.Printf("GraphicObserver:") count := generator.getNumber() for i := 0; i < count; i++ { fmt.Printf("*") } fmt.Println("") time.Sleep(time.Millisecond * 100) }(5) Client(依頼人)の役
サンプルプログラムでは、
startMain
関数が、この役を努めます。Main.gopackage main import ( "./observer" ) func startMain() { generator := observer.NewRandomNumberGenerator() observer1 := observer.NewDigitObserver() observer2 := observer.NewGraphObserver() generator.AddObserver(observer1) generator.AddObserver(observer2) generator.Execute() } func main() { startMain() }■ 参考URL
- 投稿日:2020-03-31T00:59:47+09:00