wakasa5の日記

駆け出しエンジニアの勉強録

Goで実装するLinuxコマンド ~ cat ~

きっかけ

最近、「Goならわかるシステムプログラミング」という本を読んでます。


RailsRubyの勉強を始めて半年になり、まだまだひよっこで、初心者の域を出てない身ですが、静的型付きの言語を一つ学習してみたくなったことと、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コマンドがこういう感じで実装されているのかなー?と知るのは非常に楽しいです。


勉強がてら他のコマンドや作ったコマンドの拡張を今後もやっていこうかなと画策中です。


三日坊主の自分がどこまでできるやら…


拙いコードですが、最後まで見ていただきありがとうございました!