20200331のGoに関する記事は4件です。

(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.go

WebAssembly形式でコンパイルすると「main.wasm」が生成されます。

あとは、「server.go」を実行しブラウザ経由でアクセスすることでアクセスできます。
無題.png

感想

一部Javascriptを併用する部分があり完全にgo言語のみで動的Webサイトの実装は難しいと思いました。
学習コストを抑えるためできる限りGo言語でWebシステムを実装できる様に勉強中ですが、Javascriptの知識も得るか、何らかのフレームワークを使用する必要があると感じました。

次はGoのフレームワークで多機能なサイトが作れないか調べていこうと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Golangで、デザインパターン「State」を学ぶ

GoFのデザインパターンをGolangで学習してみたいと思います。
今回は、Qiita記事: "Pythonで、デザインパターン「State」を学ぶ"で取り上げた、Pythonベースの”State”のサンプルアプリをGolangで実装し直してみました。

■ State(ステート・パターン)

Stateパターンとは、プログラミングで用いられる振る舞いに関する(英語版) デザインパターンの一種である。このパターンはオブジェクトの状態(state)を表現するために用いられる。ランタイムでそのタイプを部分的に変化させるオブジェクトを扱うクリーンな手段となる。

UML class and sequence diagram

W3sDesign_State_Design_Pattern_UML.jpg

UML class diagram

state.png
(以上、ウィキペディア(Wikipedia)より引用)

□ 備忘録

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.go
package state

import "fmt"

// State is interface
type State interface {
    handle(context *Context)
    getConcreateState() string
}

(2) ConcreteState(具体的な状態)の役

ConcreteState役は、具体的な個々の状態を表現するものです。
State役で定められたインタフェースを具体的に実装します。
サンプルプログラムでは、

  • ConcreteStateBooting構造体
  • ConcreteStateRun構造体
  • ConcreteStateShutDown構造体
  • ConcreteStateRestart構造体

が、この役を努めます。

state/state.go
type 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.go
package 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.go
package 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

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Golangで、デザインパターン「Observer」を学ぶ

GoFのデザインパターンを学習する素材として、書籍「増補改訂版Java言語で学ぶデザインパターン入門」が参考になるみたいですね。
取り上げられている実例は、JAVAベースのため、Pythonで同等のプラクティスに挑んだことがありました。
Qiita記事: "Pythonで、デザインパターン「Observer」を学ぶ"

今回は、Pythonで実装した”Observer”のサンプルアプリをGolangで実装し直してみました。

■ Observerパターン(オブザーバ・パターン)

Observerパターンとは、プログラム内のオブジェクトのイベント( 事象 )を他のオブジェクトへ通知する処理で使われるデザインパターンの一種。
通知するオブジェクト側が、通知されるオブジェクト側に観察(英: observe)される形になる事から、こう呼ばれる。
出版-購読型モデルとも呼ばれる。暗黙的呼び出しの原則と関係が深い。
分散イベント処理システムの実装にも使われる。言語によっては、このパターンで扱われる問題は言語が持つイベント処理構文で処理される。

UML class and sequence diagram

W3sDesign_Observer_Design_Pattern_UML.jpg

UML class diagram

2880px-Observer_w_update.svg.png

(以上、ウィキペディア(Wikipedia)より引用)

□ 備忘録

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.go
package 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.go
package 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.go
package 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

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Golang】Ginでサブルーティングの定義方法

やりたいこと

ルーティングを作る時にグルーピングを多段化させたい時ってあると思います。
その方法について記載します。

方法

router := gin.Default()

// api
v1 := router.Group("api/v1")
{
  // 以下のようにv1.Groupとしてv1を引き継いでGroupを作成する
  hoges := v1.Group("/hoges")
  {
    hoges.GET("/", func(c *gin.Context) {
      c.JSON(200, gin.H{
        "message": "hello",
      })
    })
  }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む