Golang 戻り値を表す変数

Golangでは戻り値に変数を割り当てることができる。

package main

import "fmt"

func doSomething() (a int) {
    return
}

func main() {
    fmt.Println(doSomething())
}

実行すると結果は0が返ってくる。

returnは何も返していないように見えるが以下のコードの省略だと考えれば良い。

func doSomething() int {
    var a int
    return a
}

var a int によって割り当てた変数aを初期化して関数の戻り値にするよいう一連の処理を、関数の戻り値の型に変数名を書くだけで済ませている。

関数内のローカル変数定義を短縮することができる。

Golang interface{}

interface{}は{}も含めて型の名前。

int, float64, stringなど全ての型と互換性をもっている。

var x interface{}
fmt.Printf("%#v", x) // "<nil>"

のように初期値は "<nil>" と出力される。

Goにおける"<nil>"は具体的な値を持っていないという状態を表す特殊な値になる。

すべての型と互換性があるため以下のように書ける。

var x interface{}
x = 1
x = 3.14
x = "ごー"
x = [...]int{1, 2, 3}

あらゆる型を代入することができる。

interface{}はあらゆる型を汎用的に表現できるものであり、演算の対象として利用することはできない。

var x, y interface{}
x, y = 1, 2
z := x + y //できない

Go 変数

Goにおけるすべての変数は型を備える。

  • 値型
  • 参照型
  • ポインタ型

値型は整数、実数といった値そのものを格納する。 参照型はスライス、マップ、チャネルのいずれかのデータ構造。 ポインタ型は値や関数といったメモリ上の実態を、アドレス値によって間接的に表現するもの。

明示的な定義

var n int

var x, y, z int

var (
    x, y int
    z string
)

上記のように予約語 var , 変数名、型名の順に定義する。

異なる型や個数が違うものを代入しようとするとコンパイルエラーが発生する。

暗黙的な定義

型推論を用いて以下のように定義することができる

a := true
b := 1
c := 3.14

など

関数の戻り値を利用することもできる。

func one() {
    return 1
}

n := one()

変数の暗黙的な定義を利用した代入は1回しか許されない。

n := 1
n := 3

nに対する2回目の代入でコンパイルエラーが発生する。

演算子 := はあくまで変数を定義するための機能であり、変数への代入を実行しているものだとイメージしてはいけない。 型指定の省略や、まとめて初期値を代入できるメリットは副次的なものである。

演算子 = は再代入の制限がないため、変数への再代入には演算子 = を使う。

var a int
a = 1
a = 2

b := 1
b = 2

ruby split

rubyのsplit メソッド

str.split(pattern = $;, [limit])

splitメソッドは、引数patternを区切り文字として文字列を分割し、配列を返します。引数の指定のしかたによってさまざまな分割ができます。分割できなかったときは、要素が文字列1つだけの配列を返します。

参照:

split (String) - Rubyリファレンス

引数でデフォルト引数が設定されている pattern = $;

$;は組み込み変数

irb(main):001:0> $;
=> nil

splitメソッドの引数を省略すると空白文字による分割になる

だから以下は同じ結果

irb(main):007:0> "1 2 3".split(" ")
=> ["1", "2", "3"]
irb(main):008:0> "1 2 3".split
=> ["1", "2", "3"]

Elixir 開発環境

Elixirの勉強を個人的に始めたので覚書を残す。

dockerでElixirを使えるようにする

以下コマンドでdocker imageをpullする

docker pull trenpixster/elixir

docker上のelixir imageを起動する

docker run --rm -v /Users/kei/takakuda/elixir_tutorial:/elixir_tutorial -it trenpixster/elixir /bin/bash

あまりdockerを使ったこともなかったのでoptionも調べる

--rm : コンテナ終了時に自動的にコンテナを削除する

-v : ホスト側のディレクトリがコンテナにマウントされ、コンテナ上で作ったファイルがホストの方に残る

-it : ターミナルでコンテナを実行できる

iexで対話シェルが動くことを確認。

Elixirのプロジェクトを作成する

mix new project

mixはビルドツール。 以下のようにフォルダ、ファイルが作成されます

.
├── README.md
├── config
│   └── config.exs
├── lib
│   └── project.ex
├── mix.exs
└── test
    ├── project_test.exs
    └── test_helper.exs

ここからelixirで開発していきます

gem 作り方覚書

準備

# gem自信のupdate
gem update --system

# bundlerのupdate
gem update bundler

# generatorからプロジェクト作成
bundle gem new_gem -t

-tはテストも作成するoption defaultでRSpec

他のgemと名前がかぶってはいけないので

gem search new_gem

で名前がかぶっていないことを確認しましょう。

雛形を作成することができたらnew_gem.gemspecを編集します

spec.summary       = %q{TODO: Write a short summary, because Rubygems requires one.}
spec.description   = %q{TODO: Write a longer description or delete this line.}
spec.homepage      = "TODO: Put your gem's website or public repo URL here."

TODOと書かれている箇所を編集していきます

summary -> サマリー

description -> 長めのサマリー

homepage -> https://github.com/takakuda/new_gem

といった感じです

# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' と書かれている箇所は社内用のgemを外部に公開しないために公開して良いホストを指定する箇所です。 RubyGems.orgに公開するのでごっそりこのあたりの記述は消します。

作成したgemをlocalで確認

new_gemを作った同じ階層にテスト用のフォルダを作成し

bundle init

Gemfileを作成します

new_gem
├── Gemfile
├── README.md
├── Rakefile
├── bin
│   ├── console
│   └── setup
├── lib
│   ├── new_gem
│   │   └── version.rb
│   └── new_gem.rb
├── miura.gemspec
└── spec
    ├── new_gem_spec.rb
    └── spec_helper.rb
new_gem_test
├── Gemfile
├── Gemfile.lock

Gemfileでは

gem "new_gem", path: "../new_gem"

でlocalのgemをinstallします

その後にbundleを実行

あとはtest用のfileを作成してgemをrequireで呼べば確認できます

確認後公開用にリポジトリを作成し、https://rubygems.org/でアカウントを作成して有効な状態にすればリリースの準備は完了です

リリース

リリースはgemspecのあるディレクトリでrake releaseを実行

自分のプロファイルページに追加されていれば完了です! https://rubygems.org/profiles/takakuda

Rubyにおける「シンボル」ってなんだ?

結局「シンボル」ってなに…

結論から言うとシンボルはRubyの内部で整数として扱われる。2つの値が同じか調べるときなど、文字列よりも高速に処理することができる。

シンボルのほうがさらにメモリの使用効率が良いらしい。

irb(main):009:0* 'a'.object_id
=> 70227007054700
irb(main):010:0> 'a'.object_id
=> 70227010342780
irb(main):011:0> 'a'.object_id
=> 70227010329420

irb(main):013:0* :a.object_id
=> 736988
irb(main):014:0> :a.object_id
=> 736988
irb(main):015:0> :a.object_id
=> 736988

シンボルは同じシンボルであれば同じオブジェクトであるということらしい。

Stringの場合はobject_idが実行ごとに変わっている

なんで「シンボル」使ってるんだろうとか考えたことなかったな… 勉強勉強…

f:id:takakudakei:20181129005549j:plain