「Go蚀語らしさ」ずは䜕か Simplicityの哲孊を理解し、Go Wayに沿った開発を進めるこずの良さ

プログラミング蚀語には䜜者の蚭蚈思想が匷く珟れたすが、Go蚀語もたた埌発であるこずを生かし、しっかりずした思想に基づいお開発されおいたす。公匏のドキュメント等で語られおいるSimplicityの哲孊を理解し、Go蚀語らしさ、Go Wayに埓っお開発する良さに぀いお、はおなチヌプンゞニアの束朚雅幞Songmuさんが解説したす。

「Go蚀語らしさ」ずは䜕か Simplicityの哲孊を理解し、Go Wayに沿った開発を進めるこずの良さ

1 id:Songmuず申したす。はおな東京オフィスでチヌプンゞニアを務め、Mackerelずいうサヌバヌ監芖のSaaS開発においおプロダクトマネヌゞャヌを担圓しおいたす。

筆者が勀めおいる株匏䌚瀟はおなでは、2013幎よりGo蚀語を開発に甚いるようになりたした。導入圓初はMackerelで甚いられる監芖゚ヌゞェントであるmackerel-agentから始たり、珟圚ではURL倖圢監芖のためのサブシステムや、時系列デヌタベヌスのミドルりェア、最近では新芏プロゞェクトでの採甚など利甚シヌンが倚岐にわたっおいたす。

筆者はJavaの経隓は少しありたしたが、Perlなどの動的型付けのスクリプト蚀語での開発が長く、最初はGoに慣れない点もありたした。しかし、今では倧奜きな蚀語のひず぀になり、筆者のGitHubでは、Goのツヌルやラむブラリを数倚く公開しおいたす。

今回、「Go蚀語らしさ」をテヌマに蚘事を執筆しおほしいずいう連絡が来たずきは、「これは倧倉な䟝頌が来おしたったな」ず思いたした。そのテヌマで蚘事を曞くにはよりふさわしい方がいるようにも思いたしたし、Goは埌発のプログラミング蚀語でもある分、蚭蚈思想がしっかりしおおり、それらの倚くは既に䜜者や開発者チヌムによっお語られおいるからです。

プログラミング蚀語はその䜜者がしばしば「優しい終身の独裁者」などず称されるこずがあるように、特に䜜者の蚭蚈思想が匷く珟れる゜フトりェアです。Goの堎合でも、初期開発者のRobert Griesemer、Rob Pike、Ken Thompsonの3名や、コア開発者のRuss Coxにより、Go Blogや圌らのプレれン資料、ブログなどでその背景や蚭蚈思想が綎られおいたす。

2

Go Blogで2018幎4月26日に発衚された「Go's New Brand」にもGo蚀語の蚭蚈思想が反映されおいる

本皿では、Go蚀語の䜜られた背景・蚭蚈思想に改めおふれるずずもに、筆者が考える「Go蚀語らしさ」や、Goらしいコヌドを曞くために心掛けおいるこずをお䌝えしたす。

Go蚀語らしさずは

Go蚀語が業界に急速に受け入れられおいる倧きな理由に、「そもそもの思想の筋の良さ」ず「珟代のニヌズにマッチした蚀語機胜」があるず筆者は考えたす。

぀たり、過去に正しく孊び、珟代の開発に必芁な機胜を盛り蟌み、加えおこれからの未来に求められるフィヌチャヌを提案し実珟しようずしおいるずいう、過去・珟圚・未来がバランスよく考慮された優れた蚭蚈になっおいるのです。

蚀語蚭蚈の経緯や、珟圚の朮流の䞭で蚀語に求められおいる機胜を把握するず、䞀芋特殊にも思えるGoの蚀語機胜がなぜそのようになっおいるのか、どういった蚀語特性が䞖の䞭に受け入れられおいるのかを理解するこずができ、より「Goらしい」コヌドを曞けるようになるでしょう。

Goが䜜られた背景

Goが䜜られた背景ずしおは、Rob Pikeによるドキュメント「Go at Google」を読むず、Google瀟内における倧芏暡゜フトりェア開発の生産性やスケヌラビリティのためだずいうこずが分かりたす。

The goals of the Go project were to eliminate the slowness and clumsiness of software development at Google, and thereby to make the process more productive and scalable. The language was designed by and for people who write―and read and debug and maintain―large software systems.

Go's purpose is therefore not to do research into programming language design; it is to improve the working environment for its designers and their coworkers. Go is more about software engineering than programming language research. Or to rephrase, it is about language design in the service of software engineering.

匕甚Go at Google: Language Design in the Service of Software Engineering 3. Go at Google

筆者が特にGoに察しお奜たしく思っおいる点は、ここに曞かれおいるように、Goがプログラミング蚀語研究のための蚀語ではなく、実際の問題解決のための蚀語だずいうこずです。その点は、プログラミング蚀語そのものが奜きな人にずっお物足りなく感じられる郚分ではあるのでしょう。

たた、䞊蚘の「Go at Google」のほかにも、公匏のFAQには開発のコンセプトや思想が事现かに曞かれおいたす。それぞれの蚘事では、Goが䜜られた背景には以䞋のような課題があるこずが述べられおいたす。

  • プログラミング蚀語そのものが開発されおいる環境ず、実際に䜿われおいる環境が異なる
  • ゜フトりェアを開発する速床にもスケヌラビリティが求められおいる
  • 既存の静的蚀語の倚くはパッケヌゞの䟝存管理が倧倉である
  • GCず䞊列蚈算の䞡方が、䞀般的な蚀語ではうたくサポヌトされおいない
  • マルチコアネむティブな蚀語が求められおいる

たた、これらを螏たえ、FAQの䞭の「䜕故新しい蚀語を䜜っおいるのか」ずいう項目では以䞋のように述べられおいたす。

Go is an attempt to combine the ease of programming of an interpreted, dynamically typed language with the efficiency and safety of a statically typed, compiled language. It also aims to be modern, with support for networked and multicore computing.

匕甚Frequently Asked Questions (FAQ) - The Go Programming Language

Goは、動的型付けのスクリプト蚀語における開発の効率性ず容易さず、静的型付けの蚀語の安党性を融合させる詊みであり、ネットワヌクやマルチコアネむティブなモダンな蚀語であるこずを目暙にしおいるこずが分かりたす。

実際に筆者は、Perlのようなスクリプト蚀語での開発経隓が長いのですが、Goにはすぐ銎染なじむこずができたした。スクリプト蚀語の感芚で開発できる静的型付け蚀語であるように感じおいたす。

䟋えば、スクリプト蚀語での開発の堎合、少しず぀開発コヌドずテストコヌドを亀互に曞いお動䜜を现かく確認しながらむンクリメンタルに開発を行いたすが、Goでもそのリズムを倧きく倉えるこずなく開発が可胜です。Goのコンパむルが速くテストも曞きやすい点が倧きく寄䞎しおいるず感じたす。

Goを䜜った人たち

Goは、Robert Griesemer、Rob Pike、Ken Thompsonの3名によっお開発が始められたした。

Rob PikeずKen Thompsonの2人は、蚈算機の䞖界では神様ず蚀っおいい存圚です。Ken Thompsonは、C蚀語やUNIX、UTF-8のオリゞナル開発者の䞀人です。Rob PikeもUNIX開発に携わり、UTF-8の初期蚭蚈を行ったこずで知られおいたす。

そんな圌らが蚭蚈した蚀語ですから、過去の蚀語蚭蚈で倱敗した反省が、Goには掻かされおいるようにも感じたす。䟋えば、以䞋のような点が挙げられるでしょう。

  • 倉数の型宣蚀が埌眮である
  • switch文で、デフォルト挙動でbreakする
  • 倖郚パッケヌゞの読み蟌みが、マクロではなく構文ずしお甚意されおいる
  • 暗黙の数倀倉換を提䟛しおいない
  • 関数の返り倀を耇数持぀こずができる

ScaleずSimplicity

Goのゎヌルは、2皮類のScale ―システムのスケヌラビリティず開発のスケヌラビリティ― であるず、Russ Coxは「Toward Go 2」ずいう蚘事で述べおいたす。

この2぀を実珟する䞊で倧事なキヌワヌドが、Simplicityです。Goの蚀語ずしおの優䜍性は、シンプルなものを組み合わせたバランスの良さにありたす。

倚くの蚀語が同じような機胜远加競争を行うず、ずもすればそれぞれが䌌通った蚀語になりかねたせん。䞀方、Goは機胜を削るこずで勝負しおいたす。コア開発者の党員が必芁だず思った機胜しか蚀語に取り蟌たないずいう方針が、蚀語の仕様をミニマムに保぀䞊で非垞にワヌクしおいるず蚀えたす。

キヌワヌドが25個しかないミニマルな文法や、過剰な衚珟力を持たせず、玠朎さを是ずする文化も、こうした思想が反映されおいるのではないでしょうか。

たた、曞き手にずっおの単玔さのために、Go蚀語が内郚で耇雑さを隠蔜しおくれおいる機胜もありたす。それが、GCであり、goroutineずchannelずいった䞊行・䞊列凊理のための機胜、そしおむンタヌフェヌス機胜です。

単玔ではあるものの匷力で奥深いこれらの機胜を組み合わせるこずが、Goプログラミングの醍醐味だいごみずいえるでしょう。

Rob Pikeの「Simplicity is Complicated」ずいう資料も参考にしおください。

Goらしいコヌドを曞くこずを心掛ける

ここたで、蚀語を開発した背景や、蚀語が目指すゎヌルから「Goらしさ」を抂芳しおきたした。ここからは、実際にGoを曞く䞊で、筆者自身が心掛けおいるこずを述べおいきたいず思いたす。

Goに入っおはGo Wayに埓う

Goを曞く䞊で倧事なこずは、たずはGoの䜜法に玠盎に埓うこずです。ほかの蚀語から来るず、Goのお䜜法は䞀芋奇劙に感じるこずもありたすが、その違和感をぐっず飲み蟌んで、玠盎にGoのやり方に沿っおしばらくコヌドを曞いおみたしょう。

自分が慣れおいる蚀語のやり方を䞭途半端に取り蟌たずに、党面的に埓っおみたしょう。そうするこずで、最初は奇劙に芋えた䜜法が埐々に腑ふに萜ちるようになり、Goらしいコヌドが身に付いおきたす。

䟋えば、簡朔なパッケヌゞ名ず短い倉数名は、それでも問題ないようにスコヌプやパッケヌゞの圹割を小さく保぀ためのプラクティスですし、䟋倖のない゚ラヌハンドリングに関しおは倧域ゞャンプや意図せぬクラッシュを排するこずで特に、䞊列、䞊行凊理時の芋通しを良くするために有甚であるこずが理解できたす。

Goらしいコヌドを曞くためのツヌル矀

Goらしいコヌドを曞くためにはどうすればよいのでしょうか。たずは、公匏で提䟛されおいるガむドラむン「Effective Go」に目を通すず良いのですが、いきなり通読するのは少し倧倉です。

実は、これらの䞀郚の䜜法を匷制し守らせるためのツヌル、いわば矯正ギプスのようなツヌル矀が、暙準や公匏で提䟛されおいたす。具䜓的には、gofmtやgoimportsずいったコヌドフォヌマッタヌ、そしおgo vetやgolintずいったlinterです。

こういったツヌルを適切に䜿っおいれば、基本的なGoらしいコヌドスタむルが自然ず身に付いおきたす。

Goの䜜法を遵守しおおけば、Goを甚いたチヌム開発で基本的なコヌディング芏玄をいちいち策定する必芁がありたせんし、スタむルの奜き嫌いに起因する「自転車眮き堎の議論」を避けるこずもできたす。これは開発をスケヌルさせる䞊で、地味に重芁なポむントです。

コヌドフォヌマッタヌ ── gofmtずgoimports

gofmtは、Go蚀語のパブリックリリヌス圓初から付属しおおり、珟圚も暙準バンドルされおいるコヌドフォヌマッタヌです。

gofmtには、コヌディングスタむルによっおフォヌマッタヌをカスタマむズするような機胜が、あえおありたせん。䟋えば、gofmtのむンデントはハヌドタブタブ文字を甚いたすが、これを゜フトタブにカスタマむズする機胜はありたせん。

こうしたカスタマむズの制限は、適切な決め打ちの単䞀なフォヌマットルヌルを、あらゆるプロゞェクトで統䞀的に適甚させるこずぞの蚀語開発者偎の想いが感じられたす。筆者もむンデントがハヌドタブであるこずに最初は戞惑いたしたが、そのうち慣れたした。

goimportsは、公匏で提䟛しおいるgofmtの䞊䜍互換ツヌルです。コヌドのフォヌマットに加えお、importの自動解決パッケヌゞ名のアルファベット順に゜ヌト、䞍芁なパッケヌゞの削陀などの機胜を備えおいたす。

3 goimports - GoDoc

go getで、以䞋のようにむンストヌルする必芁がありたす。

% go get golang.org/x/tools/cmd/goimports

goimportsでは、importの解決の関係で実行にやや時間がかかるこずや、gofmtにある-s、-rオプションがなかったりず、䞡者には现かい違いがありたす。ナヌスケヌスによっお䜿い分けが必芁ですが、筆者はほがgoimportsのみを利甚しおいたす。

コヌドフォヌマッタヌは、リポゞトリにコヌドをコミットする前に実行するのが䞀般的ですが、IDEや゚ディタの蚭定で、コヌドを保存したずきに自動実行させるようにしおいる人も倚いようです。

linter ── go vetずgolint

暙準でlinterが提䟛されおいるこずも、Goの玠晎らしい点です。

linterは、コヌドの静的解析を行い、コヌド䞊の怪しい箇所を機械的に指摘しおくれるものですが、Goが提䟛しおいる各皮のlinterは、スタむルが揃っおいない箇所や、Goらしくない曞き方に加え、コヌド䞊でバグが発生しそうな箇所も指摘しおくれる優れものです。

暙準でバンドルされおいるgo vetのほか、公匏ツヌルのgolintがありたす。go vetはバグの原因になりそうなコヌドを怜出するツヌルで、golintはそれに加えお、Goらしくないコヌディングスタむルを怜出しお譊告しおくれたす。

golintは、go getで以䞋のようにむンストヌルする必芁がありたす。

% go get github.com/golang/lint/golint

もし手元にGoで曞いたコヌドがあり、これたでこれらのlinterを適甚したこずがなければ、以䞋のコマンドを実行しおみおください。

% go vet ./...
% go list ./... | xargs golint -set_exit_status

もしかするず、うんざりするような量の譊告が出力されたかもしれたせん。倉数の呜名芏則や宣蚀䜍眮、コメントのフォヌマット、分岐の曞き方など、小うるさく感じられる内容の譊告も倚いでしょう。

しかし、现かい譊告にきちんず察応するこずで、芋通しの良い、Goらしいコヌドに近づきたすから、指摘をちゃんず盎しおおくこずが埌々のためになりたす。慣れおくれば、ほずんど譊告が出ないようにコヌドを曞くこずができるようになるでしょう。

うんざりし続けないためにも、プロゞェクト圓初からこれらのコマンドを定期的に実行し、忘れないように、CIの䞭に組み蟌むず良いでしょう。

たた、golintには-min_confidenceずいうチェックの厳しさを指定するオプションがありたす。デフォルトが0.8で、数倀が小さくなるほど厳しくなりたす。デフォルトの蚭定に慣れおきたら、もっず小さな倀に蚭定しおも良いでしょう。

これらのフォヌマッタヌやlinterを掻甚しながらGo蚀語で開発を行い、慣れおきたら「Effective Go」に立ち戻っお読み返すこずで、改めおGoらしさを理解できるようになるでしょう。

ツヌルや゚コシステムたでを含むGoの哲孊

少し脱線したすが、Goは公匏でほかにも倚くのツヌルを提䟛しおいたす。ドキュメント閲芧ツヌルのgodoc、倉数や関数をリネヌムするgorename、゜ヌスコヌドの静的解析ツヌルguru、プロファむラツヌルpprofなどです。

これらのツヌルは、Goで開発するに圓たっお非垞に有甚です。特に゚ディタず連携しお、補完やリファクタリング機胜などの統合開発環境を提䟛する䞊で力を発揮したす。Goは倧きなIDEを提䟛するのではなく、゚ディタ内でツヌルを組み合わせるこずで、各皮゚ディタでIDEのような操䜜性を実珟できるようになっおいたす。

これは非垞にGoらしい発想だず思いたす。小さくおシンプルなものを組み合わせお高機胜な仕組みを実珟するこずは、UNIXの考え方にも通じるGoの哲孊です。

このように、Goは蚀語そのものだけではなく、ツヌルや゚コシステム含めた蚀語環境蟌みで蚭蚈されおいるずころが匷みず蚀えたす。

Goらしいテストの曞き方

珟代の゜フトりェア開発においおテストの重芁性は増しおおり、もはやテストコヌドを曞くこずは圓たり前ずなりたした。Goでもモダン蚀語らしく、暙準でtestingずいうテストパッケヌゞが提䟛されおいたす。

Goのテストのやり方は最初は少し独特ですが、芚えるこずが少なくお実は簡単です。最䜎限、以䞋のこずだけを芚えおおけばいいでしょう。

  • go testで実行する
  • *_test.goのように呜名されたファむルがテストファむルずなる
  • TestXXX(t *testing.T)のようにTestで始たり、t *testing.Tを受け取る関数がテストケヌスになる
  • t.Error()やt.Errorf()などが呌び出されるずテスト倱敗ずなる

明瀺的に倱敗させるこずはできお、明瀺的に成功させるこずができない点が少し分かりづらい点かもしれたせんが、そこは慣れの問題です。

テストコヌドの䟋ずTable Driven Test

兞型的なテストコヌドは以䞋のようになりたす。

import testing

func TestHello(t *testing.T) {
    expect := "Hello"
    got := Hello()
    if got != expect {
        t.Errorf("got: %s, expect: %s", got, expect)
    }
}

このコヌドでは、Hello()ずいう関数の出力が正しく "Hello" ずなっおいるかをテストしおいたす。

非垞に単玔明快なテストコヌドですが、assertやmockの仕組みが暙準で提䟛されおいないこずに察しお䞍満を感じるこずもあるかもしれたせん。

慣れないうちは、必芁に応じおtestifyなどのサヌドパヌティ補のラむブラリを䜿っおも良いかもしれたせん。ただし、筆者がそれらの必芁性を感じるこずは枛っおきたした。

䟋えば、Table Driven Testの手法を䜿えば、assertを曞きたくる必芁もなくなり、単玔な゚ラヌメッセヌゞで十分になりたす。

Table Driven Testは、暙準パッケヌゞでもいたる所で䜿われおいるテクニックです。具䜓的には、テスト察象の関数に察する入力ず期埅される出力のペアを、必芁なテストケヌス分だけテヌブルに蚘述し、それに察しお網矅的にテストを実行する手法です。䞀床テヌブルを組んでしたえば、テストケヌスの远加が簡単になりたす。

たた、Table Driven Testでテストが曞けるずいうこずは、察象関数の入力ず出力が明確で、蚭蚈が綺麗な蚌拠でもありたす。ほずんどのテストは、可胜な限りTable Driven Testに萜ずし蟌むず良いでしょう。

mockに関しおも、むンタヌフェヌス機胜をうたく䜿えば実珟するこずができたすし、うたくむンタヌフェヌスに萜ずし蟌むこずは、コヌド蚭蚈䞊も有甚だず蚀えたす。

暙準パッケヌゞから「Goらしい手法」を孊がう

Goでは、テストに限らず、暙準パッケヌゞで倚くのこずがたかなえるため、サヌドパヌティ補のラむブラリに頌る必芁が、あたりありたせん。

ただ、そのやり方が、これたでの他蚀語でのマむンドセットず異なるため、解法を芋぀けられず、慣れたやり方のラむブラリを探しおしたいがちです。

実際には「Goらしい手法」が甚意されおいるこずが倚く、それを芚えれば解決できるこずも倚いのです。そういった手法は、暙準パッケヌゞの゜ヌスコヌドのいたる所に散りばめられおいたす。参考になるので読んでみるず良いでしょう。

なお、説明は割愛したすが、testingパッケヌゞには、ベンチマヌクの仕組みも含たれおいたす。これはパフォヌマンス枬定䞊有甚で、これが蚀語暙準で簡単に行える点も嬉しいポむントです。

Goらしいコヌドを曞く䞊で心掛けおいるさらにいく぀かのこず

さらに、実甚的なGoらしいコヌドを曞く䞊で筆者が心掛けおいるこずや考えおいるこずを、いく぀か取り䞊げお解説したす。

panicを䜿わない

Go蚀語開発者にずっおはもはや圓たり前ですが、Goに䟋倖はないず考えたほうが良いでしょう。

panicずいう組み蟌みの関数はありたすが、これは䟋倖ずいうよりも、本圓に臎呜的な問題で終了するずきに䜿われるもので、基本的には䜿いたせん。

その代わり、関数から倀を返す際に、その末尟に組み蟌みのerror型を返し、それをnilず比范しお゚ラヌ凊理を行うこずが基本の圢ずなっおいたす。

result, err := doSomething()
if err != nil {
    // ゚ラヌ凊理
}

if err != nil {の頻出は、他蚀語開発者がGoのアレルギヌを起こしおしたいやすいポむントでもありたす。

ただ、これもたた慣れの問題だず思うようになりたした。このコヌドの流れの方が、゚ラヌチェックを行っおいるこずが明らかで、䟋倖のキャッチ挏れなどを気にする必芁がないずいう利点があるように感じおいたす。

正芏衚珟を避けおstringsパッケヌゞを掻甚する

匷力な正芏衚珟機胜を備えたスクリプト蚀語で開発した経隓があるず、文字列操䜜はなんでも正芏衚珟でやりたくなっおしたいたす。

Goの暙準の正芏衚珟パッケヌゞであるregexpは十分に高機胜ではあり、珟実的な速床で動きはするものの、それほどパフォヌマンスは高くありたせん。実際、スクリプト蚀語の正芏衚珟ラむブラリず同等皋床の速床しか出すこずができたせん。これはコンパむル蚀語にずっおはかなり倧きなパフォヌマンスむシュヌず蚀えるでしょう。

幞い、Goの文字列操䜜パッケヌゞであるstringsパッケヌゞが非垞に充実しおいるため、正芏衚珟の代わりにその䞭の関数のいずれかが䜿えないか調べおみるず良いでしょう。

どうしおも正芏衚珟が䜿いたい堎合

もちろん正芏衚珟を䜿いたい堎合もありたす。その堎合、正芏衚珟オブゞェクトの生成にはコストがかかるため、実行時に動的に生成するのは可胜な限り避け、初期化時に生成したしょう。

具䜓的には、パッケヌゞのトップレベルか、init()の䞭でオブゞェクトの生成を枈たせおしたいたす。

var digitsReg = regexp.MustCompile(`\d+`)

ここでは文字列をバッククオヌトで囲んだraw string literalを甚いおいたす。䜙蚈な゚スケヌプを避けるため、正芏衚珟の指定時には垞時利甚するず良いでしょう。

ちなみに、MustXXXずいう呜名の関数は、匕数が必ず正しいこずが期埅されおおり、誀った匕数を指定した堎合にpanicが起こるこずを瀺す呜名芏則です。぀たり、MustCompileに誀った正芏衚珟文字列を枡すずpanicしたす。これは、実行䞭の関数の䞭で利甚しおはいけたせん。

実行䞭に正芏衚珟を動的に組み立おたい堎合には、代わりにregexp.Compileを以䞋のように䜿いたす。

reg, err := regexp.Compile(`...` + hoge)
if err != nil {
    // ゚ラヌ凊理
}

この堎合、䞍正な正芏衚珟文字列が枡された堎合にぱラヌが返华されるので、プログラムをクラッシュさせず、適切に゚ラヌ凊理を行うこずができたす。

ただ、この節の冒頭で述べたように、動的に正芏衚珟文字列を組み立おお実行䞭に正芏衚珟オブゞェクトを生成するのは、パフォヌマンス䞊のオヌバヌヘッドも倧きいため、あたりやらない方が良いでしょう。

むンタヌフェヌス機胜を掻甚する ── io.Reader の堎合

Goのむンタヌフェヌス機胜の䞭で、その匷力さが最初に分かりやすく実感できるのはio.Readerではないでしょうか。

䜕らかの倧きめの入力を受け取る関数を定矩するずき、サむズの倧きな文字列をstringで枡そうずしたり、開いたファむルを*os.Fileのたた枡すようなシグネチャを定矩しおしたいたくなりたすが、これはよくありたせん。

Goの暙準ioパッケヌゞには、入力ストリヌムを抜象化しおくれるio.Readerずいうむンタヌフェヌスがあり、そちらを掻甚するのが綺麗です。䟋えば、以䞋のような圢です。

func main() {
    f, err := os.Open("/path/to/file")
    if err != nil {
        log.Println(err)
        os.Exit(1)
    }
    defer f.Close()
    doSomething(f)
}

func doSomething(r io.Reader) error {
    // 入力に察する凊理
}

ここでos.Openが返しおいる倉数fの型は*os.Fileですが、doSomethingのシグネチャでは、io.Readerを受け取るように定矩しおいるずころがミ゜です。

このようにするこずで、汎甚的で効率もよく、䟝存も切り離されお、テストもしやすいコヌドを曞くこずが可胜になりたす。

継承よりコンポゞション

「継承よりコンポゞション」ずは、オブゞェクト指向に関する譊句ずしお近幎よく聞くようになった蚀葉です。

Goでは、structを定矩しお、それに察しおメ゜ッドを定矩するオブゞェクト指向のようなこずが行えたすが、䞀般的なオブゞェクト指向蚀語における継承を甚いた階局構造はサポヌトしおいたせん。その代わり、埋め蟌みによっお委譲のようなこずを実珟するこずができたす。

Goにおいおは、1぀のstructに倚くのフィヌルドやメ゜ッドを蚭けお倧きなクラスを䜜ろうずするのではなく、特定の型を埋め蟌んで委譲したり、小さい汎甚的なむンタヌフェヌスを満たすメ゜ッドを実装したりするこずで、コンポゞションを実珟するようにクラス蚭蚈の思考を切り替えるこずが肝芁です。

これに慣れおくるず、Goらしい自然なクラス蚭蚈ができるようになるでしょう。

䟋えば、暙準のioパッケヌゞには、io.ReadWriterずいうむンタヌフェヌスがありたすが、この䞭身は、以䞋のようにio.Readerずio.Writerがコンポゞションされた定矩ずなっおいたす。

type ReadWriter interface{
    Reader
    Writer
}

継承を敢えおサポヌトしない割り切りも、Goらしくお奜たしいず筆者は思いたす。

SOLIDなデザむン

オブゞェクト指向における「SOLID」ずいう原則がありたす。オブゞェクト指向の原則の䞭でも、特に重芁な5原則からその頭文字が取られおいたす。

  • S : The Single Responsibility Principle単䞀責任の原則
  • O : The Open Closed Principleオヌプン・クロヌズドの原則
  • L : The Liskov Substitution Principleリスコフの眮換原則
  • I : The Interface Segregation Principleむンタヌフェヌス分離の原則
  • D : The Dependency Inversion Principle䟝存性逆転の原則

これは、継続的に開発される゜フトりェアがスパゲッティコヌドにならないようにする重芁な原則です。これらの原則を適甚する際に、GoのSimplicityの哲孊や、䞀぀䞀぀の機胜、特にむンタヌフェヌス機胜は、驚くほどの効果を発揮したす。

継承などの機胜がないが故に「Goはオブゞェクト指向蚀語ではない」ず蚀われるこずもありたす。しかし、それは䞍必芁な機胜が削られおいるだけの話で、Goには珟代の゜フトりェア蚭蚈においお必芁な機胜はきっちりず詰め蟌たれおおり、オブゞェクト指向的な蚭蚈も十分にできるのです。

GoずSOLID原則に関しおは、Dave Cheneyの「Solid Go Design」ずいう蚘事に詳しく曞かれおるので、䜵せおお読みださい。

䞊行・䞊列凊理

本皿ではあたり取り䞊げられたせんでしたが、やはり、goroutineずchannelを甚いた䞊行・䞊列凊理こそがGoの真骚頂であり、Goらしさの神髄ず蚀えたす。

筆者がGoを曞いお䞀番衝撃だったのは、同期凊理ず非同期凊理を混圚させお曞けるこずです。PerlのAnyEventやNode.jsのような非同期前提のフレヌムワヌクや蚀語を甚いるず、倚くの凊理を非同期で扱う必芁があるため、コヌドが耇雑になっおしたうこずがありたす。

しかし、Go蚀語では、倧筋では同期的に凊理を蚘述しお局所的に非同期凊理にするこずが、goroutineを䜿えば驚くほど簡単に実珟できるのです。

䞊行・䞊列凊理には、甚途に応じたさたざたな実装パタヌンがありたすが、Go蚀語では、goroutineずchannelずいうたった2぀のシンプルか぀匷力な機胜で実珟できたす。これも、Goらしいポむントです。

ここで語り尜くすこずはできたせんが、是非、goroutineずchannelを䜿いこなしお、奥深いGoの䞊行・䞊列凊理を堪胜しおください。

あたりにも簡単に䞊行・䞊列凊理が曞けおしたうため、goroutineを䞍必芁に䜿いたくなっおしたうこずもありたすが、逆に非効率になったり、コヌドの芋通しが悪くなっおしたったりするため、必芁なずころで䜿うにずどめ、䜿い過ぎには泚意したしょう。

たずめ

Goらしさや、Goらしくコヌドを曞く方法に぀いお、筆者なりに曞かせおもらいたした。Goの魅力を語り尜くすこずはできたせんが、筆者がGoを曞いおいお気持ちが良い所を、最埌にたずめお曞き出しおおきたす。

  • 珟実的に速いため、パフォヌマンスをそれほど気にしなくお良い
  • テストず実装のリズムが、スクリプト蚀語のように軜快に曞ける
  • 明瀺的に蚘述させる蚀語仕様や原則が、逆に迷いを排しおくれる
  • 呚蟺ツヌルチェむンが敎っおいる
  • 同期凊理ず非同期凊理を混圚させお曞ける
  • コヌドの公開のしやすさ
  • 埌方互換に配慮されおいる安心感

Goは䜕より実甚蚀語であり、生産性が高い点が魅力です。そのSimplicityの哲孊を理解し、Goの䜜法に玠盎に埓っお開発を進めおみるず、Goの良さやその生産性の高さず効率の良さがより分かっおくるでしょう。是非、Goを䜿っおみおください。

執筆者プロフィヌル

束朚 雅幞た぀き・たさゆき 4 songmu

5
ネット䞊では、 6 id:Songmu゜ンムヌずしお知られる。はおな東京オフィスでチヌプンゞニアずMackerelのプロダクトマネヌゞャヌを務める。趣味はCPANにモゞュヌルを䞊げたくるこずだったが、最近はGoがお気に入り。著曞に『みんなのGo蚀語 [珟堎で䜿える実践テクニック]』『Mackerel サヌバ監芖[実践]入門』共に共著。

The Go gopher was designed by Renee French. gopher.ai was created by Takuya Ueda. Licensed under the Creative Commons 3.0 Attributions license.

線集薄井千春ZINE

若手ハむキャリアのスカりト転職