Goで実装するLinuxコマンド ~ cat ~
きっかけ
最近、「Goならわかるシステムプログラミング」という本を読んでます。
RailsやRubyの勉強を始めて半年になり、まだまだひよっこで、初心者の域を出てない身ですが、静的型付きの言語を一つ学習してみたくなったことと、turing complete FMを聞いていて、より低いレイヤの話を理解したいという欲求が出てきたことから、会社のチームの輪読会の資料に積極推しして、採用して頂いた本です。
低いレイヤとは言っても、カーネルのシステムコール叩くだけなので、本物の低レイヤの方々からみると門にすら立てていないと思いますが、エンジニア歴半年の自分にはちょうど良い感じです。
そんな中、色々と読んでいるとLinuxコマンドをGoを使って実装できそうだなと思ったので、勉強がてら実装してみることにしました。
Let's 車輪の再発明!!
実装の参考にしたブログ
既にLinuxのteeコマンドをGoを使って実装する例がこちらにありましたので、そちらを参考にさせていただきながら、Goならわかるシステムプログラミング片手に実装していきました。
参考:io.TeeReader を使って Teeコマンドを作る
私の場合はまだそれほど高度なことはできないので、一番簡単そうなcatコマンドを実装することにしました。
catコマンドの実装
実際に実装したのが下記です。
Go初心者なのでツッコミどころは満載だと思いますので、ツッコミどころあれば、ご指摘いただけると大変ありがたいです。
package main import ( "io" "log" "os" ) func main() { if len(os.Args) <= 1 || os.Args[1] == "" { log.Fatalln("filename is empty") } filename := os.Args[1] file, err := os.Open(filename) defer file.Close() if err != nil { log.Fatalln("cannot open the file") } io.Copy(os.Stdout, file) }
cat.txtを下記のように作ります。
cat dog egg
そしてbuildします。
$ go build cat.go
実行してみると…?
$ ./cat cat.txt cat dog egg
できた!!
ちなみに引数がなかったりファイルがなかったりすると下記のようなエラーメッセージが出るようになっています。
$ ./cat 2018/08/02 23:36:45 filename is empty $ ./cat dog.txt 2018/08/02 23:36:54 cannot open the file
超シンプルな実装でオプションやファイルの結合すらできない状態ですが、普段使っているLinuxコマンドがこういう感じで実装されているのかなー?と知るのは非常に楽しいです。
勉強がてら他のコマンドや作ったコマンドの拡張を今後もやっていこうかなと画策中です。
三日坊主の自分がどこまでできるやら…
拙いコードですが、最後まで見ていただきありがとうございました!
目標の奴隷になるのはやめよう 〜「仕事は楽しいかね?」を読んで〜
昨夜、急に自己啓発系の本を読みたくなったので、「仕事は楽しいかね?」を読みました。
先日、会社の役員の方にオススメされて以来、読みたいと思っていたのですが、なかなかまとまった時間が取れずだったので、ようやく読めました。
以下は本の自分なりの備忘録と感想です。
簡単なあらすじ
この本は主人公が空港に雪で閉じ込められたところから始まります。ひょんなとこから、とある老人に自分の仕事や人生の愚痴をその人にぶちまけ、老人がそれについて色々と話をするという対話形式のものになっています。
内容は堅苦しい感じではなく、完全に小説なので、誰でもスルスルと読めると思います。
人生の退屈と不安
人々は、したくもない仕事をし、同時にそれを失うことを恐れているんだ
自分は社会人4年目になりますが、前職の同期や友人と話していると、時々仕事の愚痴や組織の愚痴を聞くことがあります。
一方でそんなに嫌なら転職すれば良いやんと言うと、大体の人はいや今の収入や福利厚生を落としたくないや、異動すればきっと変わる、労働なんてそんなものだと言う返しをする人が大半です。
やりたくもない仕事をしているのに、それを失う、変えることは怖いと言うわけです。
もちろん失いたくないのは収入や福利厚生な訳ですが、そんなもののために人生の大半の時間を占める仕事を続けるのはなんとなく不思議です。
目標の奴隷
今日の目標は明日のマンネリ
よく自己啓発本では上記の不安や退屈な環境から逃れ、成功するために、下記のようなことが書かれます。
まず目標を立てましょう。なるだけ大きな目標を!自分が人生でどのようなことを成し遂げたいか?どういう状態になりたいか?本当に達成したいと心から思う目標を立てるのです。立てたらあとは簡単!毎日、それに向かって一歩一歩努力して進むだけです。
しかし、この本ではこの考えには問題があると言います。
一つはそんなやりたいことは簡単に見つからないということです。
たいていの人は、自分には夢中になれるものがないということを、なかなか認めない。だから情熱を陳腐なもののように扱ってしまう。そして、こう言うんだ、「どんなものに夢中になれるかはわからないが、『他の人と一緒に働くこと』が好きなのは確かだ」
もう一つの問題は目標を達成したからといって退屈や不安から逃れることはないということです。
アメリカの至る所で、人々は精神分析科医のところへ詰めかけ、こうぼやいている、「『ずっとしたいと思っていた』仕事をしているのに、なぜか『やっぱり幸せじゃない』んです。」
就活の時は、自分の多くの人がある程度の夢や希望を抱いて会社に入るはずです。でも数年経つと大体の人は仕事や上司、会社の愚痴を飲み会で話すことが多くなっていきます。
そう、目標を設定して、努力をして、達成したからといって、退屈や不安から逃れられることはないということです。
成功に法則はない
みんな人生のある時点で、仕事に対する目標を変えた人たちだ。
世間ではよく下記のような本や記事が出ます。
成功者はみんな〇〇をしている! 年収の高い人に共通する〇〇の習慣!
まるで成功した人が最初から成功する方法がわかっていたかのように世間は認識し、それを真似すれば成功するとそんな風に思っています。
ここである薬屋さんの話があります。その薬屋さんは色々な面白い治療薬を作ることで有名で、様々治療薬を作っていました。
ある日、薬を取りに倉庫に入ると従業員が、甘いシロップ状の薬を勝手に開けて水割りにして飲んでいました。
この時、自分が薬屋さんの店長だったらどうするでしょうか?多分、怒って従業員をクビにはしなくとも説教したりすると思います。そして薬屋さんとしてやるべきことをやるでしょう。
しかし、この薬屋さんは、確かに美味しい!ソーダで割ったらさらに美味しいそうだ!割って飲んでみよう!最高だ!となって今世界で愛されるコカコーラができたわけです。
もしこの人が薬屋として発展するために目標を掲げ、そのためにやるべきことをひたすらやっていたら、この事象は単なる邪魔なことでしかなく、さっさと片付けて何事もなく、薬屋としてやるべきことをやっていたでしょう。そしてコーラは生まれなかった。
必要は発明の母かもしれない。 だけど、偶然は発明の父なんだ。
日々挑戦しよう
「僕がいままでに掲げた目標が一つだけある。聞きたいかね?」 ぜひ、と私は答える。 「"明日は今日と違う自分になる"だよ」
それでは退屈や不安から逃れ、成功するためにはどうしたらいいのでしょうか?
一つ興味深い話をここではしています。
仮想のコイン投げ競争を想定しよう。参加者は千人、表が出れば勝ち、裏が出れば負けだ。 千人の人がコインを投げると大体500人の人が裏が出て負ける。そうして7回投げ終わるとコインを投げる人は8人くらいになる。 この頃には、コイン投げの達人を一目見ようと見物人が集まってくる。そして勝った人たちはお世辞に当惑させられる。彼らはコイン投げの天才だと褒め称えられ、生い立ちを書かれたり、急にアドバイスを求められるようになる。
そう大事なのはコインを投げ続けるということです。
だから僕は、たった一つしか目標を持っていない。毎日毎日、違う自分になること。これは"試すこと"を続けなければならないということだ。そして試すこととは、あっちにぶつかりこっちにぶつかり、試行錯誤を繰り返しながら、それでもどうにかこうにか、手当たり次第に、あれこれやってみるということだ。
感じたこと
本の内容をとてもとても簡潔にまとめてみました。他にもたくさんの良いことが書いてあるし、私の理解が正しいとは限りません。
この本を読んで感じたことは、自分の人生をより良くするのに、高尚な目標や理想などいらないということ。
就活の時から自分は自己分析というものが苦手でした。自分は好奇心が旺盛で興味があっちこっちにいくタイプで、あんまり一つのことをずっとやり続けることが苦手です。そんな自分が将来飽きないような人生の立派な目標を立てるのはとてもしんどいものでした。
まるで人生にはただ一つの立派な目標がないとダメで、それがない人は企業から評価されないみたいな。
でも働きだしてから周りをみると全くそうではありませんでした。家庭やローン、体面や収入、地位や福利厚生のために働く人たち。仕事の愚痴を言いながら何も行動しない人たち。
それでも企業の中では仕事さえしていれば評価されてクビを切られることもない。
また自分自身の価値観がどんどん変わっていくのも感じました。
そして人生の唯一の目標なんてないし、そんなものは楽しく生きるために必要ではない。人生はひたすら仮説検証で、その時の自分が楽しいと思うことをやっていけば良いやんと思うようになってきました。
そんな中でこの本と出会って、自分が感じて考えてきたことが書かれていたので、非常に共感できました。また自分の中でずっとしこりに残っていた、人生でやりたいことや成し遂げたい目標がないというコンプレックスから解放されました。
これからは目標や計画を立てることに時間を使うのではなく、やりたいこと興味があることにどんどん挑戦して、"明日は今日と違う自分になる"ことを続けていきたいと思いました。
またきっといつかマンネリにぶち当たると思います。その時はこの本を読み返して、人生のそばに置いておきたいと思いました!
是非、皆さんも興味があれば一度読んでみてください。
(ちなみにAmazon Primeの会員でkindleを使っている人なら、今(2018/07/28現在)ならPrime Readingで無料で読めるので、是非一読をお勧めします。)
Rubyのクラスについて(1)クラス定義
最近、メタプログラミングRubyやRubyの仕組みを読んでクラスについて勉強しているので、備忘録がてら内容をまとめておきます。
Rubyのクラス定義の方法
それではまず最初にRubyにおけるクラスについて書いていきます。Rubyでのクラス定義の方法は下記にようになります。
class A def hoge puts 'hoge' end end
このように定義して、newするとインスタンスができます。
pry(main)> a = A.new pry(main)> a.hoge hoge
何言ってんだと思われると思いますが、じゃあクラス定義とは実際、何を行なっているのでしょうか?
それを見ていきたいと思います。
クラス定義のやっていること
それではRubyはクラス定義で何をやっているのでしょうか?
実はRubyのクラス定義のやっていることは、Classクラスのインスタンスを生成し、定数に代入するということをやっています。
どういうことか説明していきます。まずclassクラスのインスタンスであることについて。
Rubyでは全てがオブジェクトになります。クラスも例外ではなく、クラスは実はclassクラスのインスタンスです。これはirbやpryでクラスを作って確かめてみるとわかります。
先ほど定義したclass Aのクラスを確かめてみると…
pry(main)> A.class => Class
.classはオブジェクトがどのクラスのインスタンスか確かめるためのメソッドです。結果はClassとなっていますので、AのクラスはClassクラスですね。
そんなはずはないと思う方はご自身でclass定義して確かめてみてください。
次に定数に代入しているということについて見ていきます。Rubyではアルファベットの大文字から始まる変数は定数となります。クラス定義ではみなさんアルファベットの大文字から始めると思います。
アルファベットの小文字から始めるとエラーになりますよね?
pry(main)> class a; end SyntaxError: (eval):2: class/module name must be CONSTANT class a; end ^
ここでエラーメッセージをよく見ればわかるのですが、"class/module name must be CONSTANT class"と言われています。
つまり、クラス定義は定数のクラスじゃないといけないよと言っています。先ほど、クラスはClassクラスのインスタンスだと言いました。
実はクラスはクラス定義された時にClassクラスに定数が定義されます。実際に偶然ではありえないクラス名をつけて確かめてみましょう。
(class Aだとたまたまかもしれないから念のため)
pry(main)> class HogeFugaGoGo pry(main)* def go pry(main)* puts 'go' pry(main)* end pry(main)* end => :go pry(main)> Class.const_defined?(:HogeFugaGoGo) => true
const_defined?はクラスやモジュールに定数が定義されているか、確認するメソッドです。
意味わからないクラス名ですが、classクラスに定数定義されていることが確認できました。
まとめ
これまでの検証からクラス定義がやっていることは以下の二つだとわかりました。
・Classクラスのインスタンスを作成する
・Classクラスに定数を定義する
これをもっと一般的に書くと下記をやっているということになります。
A = Class.new do def hoge puts 'hoge' end end
Aという定数にClassのインスタンスを代入しているということです。
クラス定義はその際に少し特別なことをして、Classクラスに定数への参照を加えています。
なので、クラス定義式を使わなければ、小文字でもクラスを作れます。
pry(main)> a = Class.new do pry(main)* def age pry(main)* puts 'age' pry(main)* end pry(main)* end => #<Class:0x00007ff5333d5f10> pry(main)> a.new.age age
こんな感じで。
ちなみにここら辺の説明はメタプログラミングRubyの5章に詳しく書いてあります。
もし興味のある方は読んでみてください。
終わりに
Rubyのクラス定義についてまとめました。
次回はメソッド探索についてまとめたいと思います。
自己紹介
Hello World
初めまして!
都内のベンチャーで新人エンジニアをやっているwakasa(@tak_wak_dev)と申します。
大学からずっと文系でプログラミングとは縁のない仕事をしていましたが、
17年7月からプログラミングを始め、18年1月にエンジニアに転職、
現在は主にRailsを使ったweb開発を行なっています。
このブログでは新人エンジニアとして、日々勉強していることや考えたことなどを書いていきます。
どうぞよろしくお願いいたします。
経歴
年 | 内容 |
---|---|
15年3月 | 経済学部を卒業。 |
15年4月 | メーカーで海外子会社の事業管理や市場・競合分析を担当。 |
PLや市場データの分析、中国企業の戦略分析などを行う。 | |
17年7月 | リクルートのプログラマー就職キャンプに第1期生として入学 |
HTML, CSS, JS, php, Javaを学習し、プログラミングの楽しさに目覚める。 | |
17年10月 | キャンプを最優秀で卒業。Railsの勉強開始 |
17年11月 | 大手は全て書類落ちするがベンチャーから内定獲得 |
18年1月 | ベンチャーでRailsを使ったweb開発業務に従事。 |
主にサーバーサイド、時々フロントエンジニア |