Monors Note

Pythonとそれ以外いろいろ

C#でエンディアン指定して符号なし変数に変換する。

Webの通信なのでBinaryデータを扱って、通信先でデコードする場合エンディアンを指定する必要があります。 Webでは基本的にBigEndian形式で変換されたデータを使用して、通信が行われます。一方PC上の内部構造はLittleEndianが使用されています。 C#でリトルエンディアンをビッグエンディアンに変換する - PG日誌

下記でPC上でどちらが使用されているかを確認することが可能です。

Console.WriteLine(BitConverter.IsLittleEndian); 

ネットワークの場合、符号付き整数を扱う場合のみ、 IPAddress.NetworkToHostOrder を使用すればBigEndian方式に変換することが可能です。IPAddress.NetworkToHostOrder メソッド (System.Net) | Microsoft Docs

しかし、符号なし整数の場合は、Network関係のメソッドにはメソッドが用意されていないので、別のメソッドを使用する必要がある。 そこで発見したのがBinaryPrimitives.ReadInt16LittleEndian(ReadOnlySpan<Byte>) メソッド (System.Buffers.Binary) | Microsoft Docs

using System.Buffers.Binary;
var value = 16UL;

// BitConverterはLittleEndianでエンドードさていている。
var intValue = BitConverter.GetBytes(value);
Console.WriteLine(BinaryPrimitives.ReadUInt64LittleEndian(new ReadOnlySpan<byte>(intValue)));

var bytes = new byte[8];
// BigEndianでエンコード、デコードする。
BinaryPrimitives.WriteUInt64BigEndian(bytes, value);
Console.WriteLine(BinaryPrimitives.ReadInt64BigEndian(new ReadOnlySpan<byte>(bytes)));

参考

golang のtoolの管理に関して

開発をしているとソース内では使用しないが、便利なtoolをgo getしバージョンの管理をしておきたいことがある。 例えば、golang.org/x/tools/cmd/stringerなど。
しかし、go moduleで依存関係を管理している場合、ソースないで使用されていないライブラリは管理できないという制約がある。これをtools.goを作成する方法で回避できるのでメモしておく。

github.com

// +build tools 

package tools

import _ "golang.org/x/tools/cmd/stringer"

build時に今回作成したtoolsファイルが除外される様にbuild constraintsを使用している。

golang.org

これを使用することで、build -tags=hogeで切り替えを行うことが可能であるが、これを指定しないので、binaryにはtoolsのファイルは含まれない事になる。

qiita.com

for { select {....} }はbreakではfor文を抜けられ無い

golangでtimeoutなどの処理を書く場合に、下記の様にfor文内にselectを記述することがある。 (この時Timeout時にはfor文を抜けたいとす。)

for {
  select {
    case someChannel:
       // timeout以外の処理
    case time.After(1 * time.Secound):
      // timeout時の処理
      break
  }
}

しかし、単純にbreakを記述しても、for文を抜けることは出来ない。 for文を抜けるには、Labelを用いてbreakをする必要がある。

Loop:
for {
  select {
    case someChannel:
       // timeout以外の処理
    case time.After(1 * time.Secound):
      // timeout時の処理
      break Loop
  }
}

また、breakではなく、returnを使って関数から抜けることを行えば、labelを使用する必要はなくなる。

ioパッケージでのファイル書き込み

goのioパッケージにはOpenFileという関数がある。これは、ファイル名、ファイルに対する操作、ファイルのPermissionを設定して、File構造体を作成する関数であうる。

io.OpenFile(filename string, flag int, permission int)

golang.org

ファイルに対する操作

ファイルの操作には下記の通りである。

const (
        // Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.
        O_RDONLY int = syscall.O_RDONLY // open the file read-only.
        O_WRONLY int = syscall.O_WRONLY // open the file write-only.
        O_RDWR   int = syscall.O_RDWR   // open the file read-write.
        // The remaining values may be or'ed in to control behavior.
        O_APPEND int = syscall.O_APPEND // append data to the file when writing.
        O_CREATE int = syscall.O_CREAT  // create a new file if none exists.
        O_EXCL   int = syscall.O_EXCL   // used with O_CREATE, file must not exist.
        O_SYNC   int = syscall.O_SYNC   // open for synchronous I/O.
        O_TRUNC  int = syscall.O_TRUNC  // truncate regular writable file when opened.
)

ここで、注目いたいのはO_RDONLYO_WRONRYO_RDWRは必ず一つ選ぶ必要があると言うことである。

これら3つはファイルをどの様に開くかのみを定義している。 ファイルに書き込みを行いたい場合は別途O_APPENDを呼び出す必要がある。

Permission

ここで指定するPermissionはLinuxなどのPermissionと同じ形式で指定する。

`go`でコマンドのフラグを扱う

golangでコマンドを作成した場合、フラグによって動作を分けたい場合がある。 この動作はflagパッケージを使うことで可能である。

公式ドキュメント https://golang.org/pkg/flag

非フラグを受け取る

cmd 1 2 3など、-hogeでフラグを指定しないことも可能である。 この場合、ソース内では配列として受け取る。

package main

import "flag"

func main() {
  flag.Parse()
  flags := flag.Arg() //[]stringが返る。
}

フラグを使って受け取る。

cmd -flag somthing-flagを指定してフラグを渡すこともかのである。

package main

import "flag"

func main() 
  // flag.Int(flag_name, default_value, hlep_message)
  f := flag.Int("f", "0", "message")
}

Dockerによるアプリケーション開発環境構築ガイド

Dcokerによる基本的なコマンド

Dockerコマンドのシーン毎の利用例

1. Dockerイメーシを取得しRunする。 - docker imageをpullする。 docker pull - imageからconteinerをrunする。 docker run -d //demon化 -it //擬似TTY --name hoge ubuntu:16.04 bash

2.ターミナルからphpをインストールして、新しいイメージを作成する。 - 1で起動したコンテナに入る。docker exec -it //擬似TTYで接続します。(Docker内でコマンドの実行のみをしたい場合は不要?) hoge bash - 起動したコンテナで色々作業をする。 - 上記の操作を反映したコンテナのイメージをcommitで作成する。docker commit hoge - 作成したdocker imageにtagをつける。docker tag [作成されたID] smpledokcer1234/ubuntu_with_php:1_0

<疑問> docker run -it <- itってなんで必要なの? <答え> 作成したDcokerの標準入出力を中継してくれる擬似的なTTYというものを作成する。 これを指定しないと、docker exec -it hoge bashなどしても the input device is not a TTYと言われて怒られる。

3.作成したイメージをファイルに出力して、一度手元から消した後にファイルを読み込んで復元 - imageをファイルに保存する。docker save -o /tmp/ubuntu_with_1_0 sampbledocker1234/ubuntu_with_php:1_0 - imageを一旦消す。 docker irm sampledocker1234/ubuntu_with_php:1_0 - loadコナンをを用いてファイルの読み込みを行う。docker load < /tmp/ubuntu_with_php_1_0

4.ローカルファイルをコンテナにコピー、逆にコンテナのファイルをローカルにコピーする - ローカルマシーンのファイルをDockerにコピーする。touch samplefile | docker cp samplefile [dockerID] - Dockerコンテナのファイルをローカルにコピーします。docker cp [dockerID]:samplefile /temp/

DockerfileでオリジナルのDcokerを作成する。

Docker CommitではOriginalのDocker Imageを元に任意の処理を行ったのちに、Imageを作成する事ができました。 しかし、この方法ではどのImageを使用してどの様な操作を行ったのかを後から確認するには大変です。 どのため、Dockerにはdocker buildというDcokerfileというファイルで定義した一連の手続きをコンテナイメージを作成する仕組みです。

Dockerfileとは

Dcokerfileには下記を指定する事が可能です。 - Dcokerイメージの指定 - 必要なパッケージのインストール - ファイルやディレクトリのコンテナ内のコピー - ユーザアカウントの作成や任意のコマンドの実行

Dockerfileで使用できるコマンド

Dockerfileを記述するのに最低限必要なコマンドは下記の通りです。

コマンド 意味
FROM ベースとなるDockerイメージを指定するコマンド
ENV 環境変数を設定するためのコマンド
ARG buildをする際に利用する引数を定義するコマンド。
デフォルト値を持つ事もできる。
buildコマンドからは--build-agesオプションにより利用する。
LABEL Dockerイメージにメタデータを付与するためのコマンド
RUM shellの実行を行うためのコマンド
SHELL デフォルトのコマンドを設定するためのコマンド
WORKDIR 起点となるディレクトリを変更するためのコマンド。
この設定を行うとRUN, CMD, ENTRYPOINT COPY, ADDのコマンドで相対パスが使われた時はそのデフォルトを起点として解釈される。
ADD ファイルやディレクトリおよび指定されたURLリソースをコンテナの指定されたパスに対してコピーするコマンド。
圧縮されている場合は解凍されてコピーされる。
COPY ADDの解凍されずにcopyされる版
EXPOSE コンテナがlistenするポート番号明示するためのコマンド。
あくまでも明示的に宣言するだけで実際に宣言しないとポートが開かない訳は無い。
ただし、実行時には正しく-pオプションにsてdockerホストとのポートを接続する必要はある。
ENTRYPOINT コンテナ起動時に事項するコマンドを指定するコマンド
CMD ENTRYPOINTと同じ

dockerでのポート

Docker内部にアプリをインストールした場合、そのアプリに対して通信を行う必要が出てくる。 この様な場合、docker内部のアプリと通信を可能にするために、ポートを設定する必要がある。

ポートの指定はdocker run -p [hostのIPを指定(ex: localhost)]:[host側のポートを指定]:[Docker側のポートを指定]を使用すれば可能です。

例えば、ホスト側の80ポートに対してDockerの80ポートをバインドしたい場合は下記の通り設定を行う。

▶︎入力

docker run -d -p 80:80 sample:nginx

▶︎出力

CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS                      PORTS                                                                                       NAMES
4fb9e407daa6        sample:nginx            "nginx -g 'daemon of…"   7 hours ago         Up 7 hours                  0.0.0.0:80->80/tcp 

(追記予定)

※「Dockerによるアプリケーション開発環境構築ガイド」を読んで内容を自分なりにまとめたものです。

Amazon CAPTCHA