Heroku via Dropbox; Part 2
HerokuのDropbox Syncが終了するとのこと。おせわになりました。
Support for Dropbox Sync will end on 24 July 2018.
前回からの続き
Heroku via Dropbox - sugilogのブログ
やること
- Bootstrapなテンプレートを適用して、HTMLの中身を書き換える。
- ちなみにサイトここ→ http://sugilog-profile.herokuapp.com/
手順
好きなテンプレートを探す。
たとえば、Start Bootstrapで探してみる。
今回は、ここのGrayscaleなテンプレートを使います。(Download!)
ファイル設置
ダウンロードして展開したファイルの中身をDropboxのディレクトリ(Herokuのサイト向けのディレクトリ)につっこむ。
lessとか本当はいらないけど、とりあえずは細かいことは気にしない。
デプロイ
Herokuの管理画面からデプロイ!
確認してみます。
↓↓↓
うまくいかない場合
デプロイして、失敗する時がある。
- 今やっている方法だと、Herokuにphpで書かれたアプリケーションとして認識されているのだけど、phpファイルが無いと思われる(らしい)。
- そういうときは、phpファイルに空文字を足すとかして編集保存して、わざと変更があった状態にしておくと、うまくいくかもしれない。
Heroku via Dropbox
HerokuのDropbox Syncが終了するとのこと。おせわになりました。
Support for Dropbox Sync will end on 24 July 2018.
Herokuのデプロイ方法に、Dropbox Syncが追加されていたらしいので、試してみる。
とりあえず、できるだけ簡単に、HTMLを設置して表示することを目指す。
前提
- Dropboxアカウントを持っている。
- なければ作ってください。
- Herokuアカウントを持っている。
- なければ作ってください。
- なんか、シングルページのHTMLで、何かしら公開したい人。
- プログラムを組む気はないし、Facebookとかで公開してればいいし、ぐらいな人。
- HTMLを少しいじれる人。
Gitを使わなくて良くなるので、簡単なことはHerokuで、無料でできちゃう、とか思ってます。
手順
Herokuで新しくAppを作成する。
App = 新しいサイト、ということで、まずは設置場所をつくる。
ログインをして
右上の「+」のリンクをクリックして
Appの名前(サイト名っぽいのん)を入力する。
ここで入力した内容は、デフォルトでのサブドメインになる。
Dropboxと連携する。
予め連携したいDropboxのウェブサイトにログインしておくと良いです。
「Deploy」タブで「Dropbox」を選んで
「Connect to Dropbox」な感じで進んで
連携を承認して
おわりです。
Dropboxをみると、Dropbox > Apps > Heroku > (入力したApp名)
でディレクトリが作られる。
ファイル設置
ここだけ、自分のパソコンで作業。
ここでは、index.html
とindex.php
の2つのファイルを設定してみます。
Dropbox > Apps > Heroku > (入力したApp名)
なディレクトリの下に置く感じ。
- その他のディレクトリは無視ってください。
HerokuにDropbox経由でStaticなファイルを設置してみる
デプロイ
HerokuのDropbox Syncは自動的にデプロイされるわけではないので、Herokuの管理画面から作業が必要です。
- おかげで、Dropboxにファイルを設置したまま、作業ができて便利。
「Deploy」タブの「Dropbox」から
「Deploy Changes」のメッセージに変更内容の要約を入力して
「Deploy」押して、少し待つと完了。
表示されました。
Go言語:Channelsのselect
select の話
- selectステートメントで、複数のChannelsを条件分岐できる。
- 受信、送信、どちらも可能。
- Channelsの送信があるのに、受け取りを行ってなかったら、selectをしていない場合と同じで例外になるので注意。
- 複数条件に一致する場合は、ランダムに選択される。
- selectの中のいずれにも該当しない場合の条件を
default
で指定可能。- Channelsに限定した話ではない。注意。
試してみた
実行結果
start? 1 0 0 1 1 2 1 3 2 4 3 5 5 6 8 7 13 8 21 9 34 10 55 11 89 12 144 13 233 14 377 15 610 16 987 17 1597 18 2584 19 4181 quit 0 0 1 1 2 1 3 2 4 3 5 5 6 8 7 13 8 21 9 34 10 55 11 89 12 144 13 233 14 377 15 610 16 987 17 1597 18 2584 19 4181 quit
コード中のコメントアウトしているdefault
内の行を解くと、演算実行の間(繰り返されている間)に、何度もdefault
が呼び出されていることがわかる。
Go言語:数値型の幅
フィボナッチなサンプルを写経して動かしていた時にやっと理解した。
Go言語の数値型(の整数)
- intはジェネリックであり、実行環境に依存したサイズ(値の扱える範囲)を持つ。
- 範囲を超えた場合は、オーバーフローを起こす。
- 数値演算を行った結果、扱える範囲の最小または最大を超える。
- オーバーフローが発生しても例外は発生しない。
- ただし、リテラルの場合は、例外が発生する。
- わかりきったオーバーフローのためと推測。
- オーバーフローしたら破棄され、ラップアラウンドが発生する。
- 扱える範囲の最大値に達した後に、最小値に戻る。
- 扱える範囲の最小値に達した後に、最大値に戻る。
ラップアラウンドが発生するため、
x < x + 1
が常に成り立つとは限らない。ラップアラウンドを発生させる使用であるため、暗黙的な型変換は発生しない。
なぜGoには暗黙的な数値変換がないのですか?
C言語における数値型での自動型変換の利便性は過剰であり、混乱を招く原因となっています。式が符号無しなのはいつか? 値の大きさはどの位? オーバーフローする? 型変換の結果はポータブルで実行されるマシンに非依存? これはコンパイラも複雑にします。「通常の算術変換」の実装は簡単ではなく、アーキテクチャ間で一貫性を保つことも簡単ではありません。私たちは移植性の理由から、コード中で明示的に型変換をする労力を払うことによって、明確で解り易くする決断をしました。それでも、Go言語での定数の定義(符号およびサイズのアノテーションの要らない任意精度の値)は問題をかなり改善しています。
これと関連しますが、C言語とは違い、仮にintが64ビットだったとしても、intとint64は明確に別の型となります。int型はジェネリックです。整数が何ビットあるのかを気にしたい場合、Go言語では明示的に指定することが推奨されます。
試してみる
実行環境は64bitマシン
実行結果
overflowIntWithLiteral 9223372036854775807 + 0 => 9223372036854775807 overflowInt 9223372036854775807 + 0 => 9223372036854775807 9223372036854775807 + 1 => 9223372036854775806 overflowUint8Max 255 + 0 => 255 255 + 1 => 254 overflowUint8Min 0 - 0 => 0 0 - 1 => 255
コード中のコメントアウトを解いて実行すると、
# command-line-arguments ./overflow.go:21: constant 9223372036854775808 overflows int
Rubyで慣れきってて、めちゃくちゃに大きい数値を扱うことが少ないと、下手にラップアラウンドを罠として踏みそう。
大事なのは、明示的にプログラミングすることと、そのための想定。
Go言語:Channesの制限
Channelsの話
- Channelsはバッファにすることができる。
- 容量を指定することが可能。
make
関数の第2引数に指定。
cap
とlen
の実行が可能。- 容量
cap
以上にはバッファ(値の送信)できない。ブロックする。 - バッファサイズ
len
以上には取り出し(値の受信)できない。
- 容量
- 送信する値がなくなったら、Channelsを閉じることができる。
- 受信側で閉じない。
- 閉じることは必須ではない。
- Channelsの受け取り側で、閉じられているかどうかがわかる。
- 受信のチャネルオペレータの2番目のパラメータ(boolean)がcloseかどうかがわかる。
- 閉じられている場合、バッファサイズ以上の取り出し(値の受信)が可能。
- 受信される値は型のデフォルト値(だと思う)。intなら0。
range
で受信すると、閉じられるまで繰り返される。range
を使う場合は、必ず閉じなければいけない。- 実行時エラーになる。
書いてみた1
出力
before send 0 2 after send 2 2 received value 1 2 after receive 0 2
コメントアウトを解いてみると、fatal error
が発生する。
- 容量以上に送信しようとした時。
- バッファサイズ以上に受信しようとした時。
- コンパイル時にエラーにはならないため、実行時エラーとなる。
- エラーの内容から、送信か受信かがわかる。
all goroutines are asleep - deadlock! goroutine N [chan send]:
fatal error: all goroutines are asleep - deadlock! goroutine N [chan receive]:
書いてみた2
range
0 1 1 2 3 5 8 13 21 34
rangeじゃない
0 true 1 true 1 true 2 true 3 true 5 true 8 true 13 true 21 true 34 true 0 false
rangeでcloseしなかった場合。
- 実行時エラーで以下のようなエラーが出る。
- エラーするのは、
range
の行。
fatal error: all goroutines are asleep - deadlock! goroutine N [chan receive]:
rangeを使わない受信でcloseしなかった場合。
- 書いてみた1で記述したとおり、実行時エラーする。
Go言語:Goroutines
goroutine (ゴルーチン)は、Goのランタイムに管理される軽量なスレッドです。
go 関数呼び出し
で新しいスレッドで処理される。- プログラムは、スレッドの処理の終了を待つわけではない。
- 新しいスレッドで処理が始まるのに(ノンブロックの状態で)遅延がある。
- Channelsを使うと、簡単に同期的な処理が書ける。
- 条件を明示せずに、同期を許可する、ということらしい。
- Channelsの操作には、channel operator
<-
を用いる。 channel <- x
でChannelsに値を送信、y := <- channel
で受信し変数へ値を割り当てる。
- Channelsの生成には、
make
を用いる。make( chan 型 )
- 型以外の値を送信しようとすると、
cannot use xxx (type xxxの型) as type 正しい型 in send
としてコンパイルに失敗する。
書いてみる1
sample.goの出力
- goroutineでの処理が遅れて実行される。
- goroutineでない処理とは並行して処理が進む。
0 second 0 first 1 second 1 first 2 second 2 first 3 second 3 first 4 second 4 first
sample.nooutput.goの出力
- なにも出力されない。
- プログラムのほうが早く終了する、という理解で合ってる?
sample.sleep.goの出力
go
の呼び出しの後にsleepを入れた。- goroutineでの処理が先に実行される。
- たまたま、1ミリ秒以内でgoroutineの処理が先に始まった、という方が正しいかもだが。
0 first 0 second 1 first 1 second 2 first 2 second 3 first 3 second 4 first 4 second
書いてみる2
ポインタはgoroutineでないときと同じように振る舞うらしい。
出力
1 0 1 2 0 2 3 0 1 1 1 3 2 1 4 3 1 2 1 2 5 2 2 6 3 2 3 1 3 7 2 3 8 3 3 4 1 4 9 2 4 10 3 4 5 10
書いてみる3
- ポインタで書くより明らかにわかりやすい。
- 同期したいタイミングが明示できる。
invoke Channel A 1 0 1 2 0 2 1 1 2 2 1 4 1 2 3 2 2 6 1 3 4 2 3 8 1 4 5 2 4 10 5 10 invoke Channel B 3 0 3 3 1 6 3 2 9 3 3 12 3 4 15 4 0 4 4 1 8 4 2 12 4 3 16 4 4 20 15 20
Go言語:HTTPサーバーのコーディングをしてみる
↓のslideshareのコードを写経していく。
写経させていただきました。資料ありがとうございます!
とりあえずコーディング
HTTPサーバーの写経// http://www.slideshare.net/yasi_life/ ...
構成
- GOPATH/src/server.go
- サーバープログラム
- GOPATH/views/view.html
- 表示画面のテンプレート
- GOPATH/views/edit.html
- 編集画面のテンプレート
まだやっていないこと
- セキュリティとか、全然考えてない。
- セッションも何もない。
- 相対パスでアクセスしているので、プログラムと関係ない変なファイルにアクセスできるかもしれない。
- とか。
- 保存失敗した時の処理をしていない。
- 名前に
/
が含まれている場合に、このコードだとno such file or directory
が出る。 - でもそのメッセージをユーザーに返していない。
- 名前に
思ったこと
- 簡単なレベルの実装であれば、すごい簡単。
- 提供されているパッケージが充実している印象。
- ルーティングに関数を渡すのは読みやすい。
- JavaScript勉強していた人がGo言語やるとか、いいかも。
- JavaScriptでイベントドリブンな実装を中心にやっていた人が、か。