Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/go webassembly #12

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions docs/go-webassembly/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,10 @@ <h2>DOMの操作</h2>
message := window.Get(&#34;document&#34;).Call(&#34;getElementById&#34;, &#34;message&#34;)

// イベントリスナーとして登録するコールバックを作成
cb := js.NewCallback(func(args []js.Value) {
cb := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
// HTMLを変更する
message.Set(&#34;innerHTML&#34;, &#34;Clicked!!&#34;)
return nil
})

// イベントリスナーの登録
Expand All @@ -324,14 +325,12 @@ <h2>DOMの操作</h2>
}</code></pre>
<p><code>getElementById</code>でHTMLの要素を取得する部分は、<code>2_dom</code>のサンプルとあまり変わりはありません。しかし、このサンプルでは取得したHTMLの要素にクリックイベントのリスナーを設定しています。</p>
<p>クリックイベントをハンドリングするには、JavaScriptで書いた例と同様に、<code>addEventListener</code>メソッドを呼び出し、クリックイベントのイベントリスナーとしてコールバック関数を登録する必要があります。</p>
<p>コールバック関数は、Goの世界の関数をJavaScriptの世界の関数として<code>addEventListener</code>メソッドに渡す必要があるため、単純なGoの関数ではなく、<code>syscall/js</code>パッケージの<code>js.Callback</code>型として定義する必要があります。<code>js.Callback</code>型の値は、<code>js.NewCallback</code>関数を用いることで作成することができます。作成したコールバック関数は<code>addEventListener</code>メソッドの引数として渡しています。</p>
<p>コールバック関数は、Goの世界の関数をJavaScriptの世界の関数として<code>addEventListener</code>メソッドに渡す必要があるため、単純なGoの関数ではなく、<code>syscall/js</code>パッケージの<code>js.Func</code>型として定義する必要があります。<code>js.Func</code>型の値は、<code>js.FuncOf</code>関数を用いることで作成することができます。作成したコールバック関数は<code>addEventListener</code>メソッドの引数として渡しています。</p>
<p><code>main</code>関数の最後にある<code>select{}</code>は<code>main</code>関数をブロックする役目があります。JavaScript側で発生したクリックイベントは、<code>syscall/js</code>パッケージで管理されているイベントループに通知されます。</p>
<p>イベントループのゴールーチンは<code>main</code>関数が動いているゴールーチンは別ですが、<code>main</code>関数のゴールーチンが終わってしまうとGoで書いたプログラム自体が終了するため、イベントループのゴールーチンも一緒に終了してしまいます。Goのプログラムが終わってしまうとJavaScript側はイベントをハンドリングしてくれる相手がいないため、エラーを発生させます。</p>
<aside class="warning"><p><strong>コールバック関数でデッドロックが起きる場合は</strong></p>
<p>コールバック関数は1つのゴールーチンの中で1つずつ処理されます。そのため、コールバック関数の中で、コールバック関数によって結果を受け取るような処理があるとデッドロックが起きてしまいます。例えば、<code>net/http</code>パッケージの<code>http.Get</code>などの関数は<code>js/wasm</code>の環境では、<code>fetch</code>というJavaScriptの関数を用いて実装されています。そのため、内部でコールバック関数を用いています。もし、コールバック関数内でこれらの関数を呼び出したい場合は、別のゴールーチンを起動して呼び出す必要があります。</p>
</aside>
<p>ここではクリックイベントについて紹介しましたが、その他のイベントについても同様にハンドリングすることができます。また、<code>preventDefault</code>などの処理をしたい場合には、<a href="https://tip.golang.org/pkg/syscall/js/#NewEventCallback" target="_blank"><code>js.NewEventCallback</code></a>関数を用いるとよいでしょう。</p>


</google-codelab-step>

Expand Down
3 changes: 2 additions & 1 deletion go-webassembly/3_clickevent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ func main() {
message := window.Get("document").Call("getElementById", "message")

// イベントリスナーとして登録するコールバックを作成
cb := js.NewCallback(func(args []js.Value) {
cb := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
// HTMLを変更する
message.Set("innerHTML", "Clicked!!")
return nil
})

// イベントリスナーの登録
Expand Down