Go言語初心者がハマった2つのポイント
こちらはeureka Advent Calendar 2016 21日目の記事です。
前回は臼井さんの「regexpとの付き合い方 〜 Go言語標準の正規表現ライブラリのパフォーマンスとアルゴリズム〜」でした!
こんにちは。エウレカでpairsを担当しています @takochuu と申します。
今回の記事では、今年の7月まではインタプリタ型の言語でずっと開発していた僕が
どのようにGo言語のキャッチアップに取り組んだかを紹介します。
こちらの二川さんの記事にあるように
エウレカではpairsとCouplesという2つのプロダクトを展開しており、pairsではサーバーサイドは全てGo言語で記述されています。
前職ではPerlを使って業務を行ってきた僕には、コンパイル型の言語であるGo言語での開発をキャッチアップする過程で様々なハードルがありました。
今回は実際に僕がハマった一例についてご紹介します。
インターフェースを用いたプログラミングについて
Go言語にはクラス・継承という概念が存在しないのでインターフェースを用いて実装を行います。
※ http://golang.jp/go_faq#inheritance
インターフェースを用いた実装のサンプルとして、
下記は標準出力へ”hogehoge” という文字列を出力するためのプログラムです。
package main
import (
"fmt"
"os"
)
func main() {
fmt.Fprintf(os.Stdout, "hogehoge\n")
}
Fprintf
メソッド(リンク張る)は、第一引数に io.Writer
型を取り、 w.Write(p.buf)
を呼んでいます。
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
p := newPrinter()
p.doPrintf(format, a)
n, err = w.Write(p.buf)
p.free()
return
}
次にio.Writer
のソースコードを確認すると Write
というメソッドを定義したインターフェースであることがわかります。
type Writer interface {
Write(p []byte) (n int, err error)
}
os.Stdout
を渡しているのに Fprintf
が問題なく動作するのはなぜでしょうか。 ここで os.Stdout
をのぞいてみます。
var (
Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)
os.Stdout
は os
パッケージ内の公開されている定数であり、右辺を見ると NewFile
を呼んでいます。
NewFile
の返り値は *File
型であるため os.Stdout
には *File
型の構造体が入っていることになります。
func (f *File) Write(b []byte) (n int, err error) {
if f == nil {
return 0, ErrInvalid
}
n, e := f.write(b)
if n < 0 {
n = 0
}
if n != len(b) {
err = io.ErrShortWrite
}
epipecheck(f, e)
if e != nil {
err = &PathError{"write", f.name, e}
}
return n, err
}
上記のように File
構造体はWrite
メソッドを実装しているため、io.Writer
のインターフェースを満たすと判定され、引数として扱うことができます。
パッケージレイアウトの学び方について
書き方については、上記の例を挙げましたが、Go言語を学ぶなかでもう一つハマったのがパッケージレイアウトでした。
僕がパッケージレイアウトを学んだオススメの方法は、標準パッケージ群を読むことです。

上記はtimeパッケージのソースコードになりますが、ディレクトリ階層がなくフラットになっていることがわかります。
Go言語においてはこのようにパッケージ内のディレクトリを深くせず、フラットに実装するのが1つのパターンではあります。
ただ、Go言語においてのパッケージレイアウトについては語られることが多くなく、書かれている記事はこちらぐらいしか見つけることができませんでした。
View story at Medium.com
こちらの記事では以下のように書かれています。
Vendoring. Generics. These are seen as big issues in the Go community but there’s another issue that’s rarely mentioned — application package layout.
ベンダリングとジェネリクスはgoコミュニティの大きな問題ですが、もう一つの大きな問題であるapplication package layoutについてはほとんど言及されることがないようです。
僕は、パッケージレイアウトについては標準パッケージを参考にするという考え方をしています。
記事内で筆者はパッケージレイアウトについて提言をしてくれているのですが、
上記記事で紹介されているレイアウトが一般的になっているとは言い難い現状なのではないかと感じています。
少し抽象的になってしまいますが、import cycle
を避ける目的と依存が深くなるのを避けるために、フラットに実装するのが現時点では良いと考えています。
良いアプローチをお持ちの方がいれば教えていただきたいです。
#これからgoを学ぶ方へ
結論が抽象的な話を書いてしまいましたが、Go言語は薄く書けるし、書いていてとても楽しい言語です!
最後に、Go言語初学者が読んでおくと良い記事を紹介します。
https://talks.godoc.org/github.com/davecheney/introduction-to-go/introduction-to-go.slide#1
※Go言語の作成者であるDave cheneyさんがGo言語の構文やインストール方法について解説しています。
http://talks.godoc.org/github.com/davecheney/high-performance-go-workshop/high-performance-go-workshop.slide#1
※Dave Cheneyさんがベンチマークのとり方やプロファイリングについて解説している資料です
上記記事は日本語ではありませんが、サクっと探したWebの記事には書いていない内容が多くオススメです。
今年も残り短くなりましたが、皆様良いGolifeを!
そして、明日は森川さんです。お楽しみに!
エウレカでは、一緒に働いていただける方を絶賛募集中です。募集中の職種はこちらからご確認ください!皆様のエントリーをお待ちしております!
こちらはeureka Advent Calendar 2016 21日目の記事です。
前回は臼井さんの「regexpとの付き合い方 〜 Go言語標準の正規表現ライブラリのパフォーマンスとアルゴリズム〜」でした!
こんにちは。エウレカでpairsを担当しています @takochuu と申します。
今回の記事では、今年の7月まではインタプリタ型の言語でずっと開発していた僕が
どのようにGo言語のキャッチアップに取り組んだかを紹介します。
こちらの二川さんの記事にあるように
エウレカではpairsとCouplesという2つのプロダクトを展開しており、pairsではサーバーサイドは全てGo言語で記述されています。
前職ではPerlを使って業務を行ってきた僕には、コンパイル型の言語であるGo言語での開発をキャッチアップする過程で様々なハードルがありました。
今回は実際に僕がハマった一例についてご紹介します。
インターフェースを用いたプログラミングについて
Go言語にはクラス・継承という概念が存在しないのでインターフェースを用いて実装を行います。
※ http://golang.jp/go_faq#inheritance
インターフェースを用いた実装のサンプルとして、
下記は標準出力へ”hogehoge” という文字列を出力するためのプログラムです。
package main import ( "fmt" "os" ) func main() { fmt.Fprintf(os.Stdout, "hogehoge\n") }
Fprintf
メソッド(リンク張る)は、第一引数に io.Writer
型を取り、 w.Write(p.buf)
を呼んでいます。
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { p := newPrinter() p.doPrintf(format, a) n, err = w.Write(p.buf) p.free() return }
次にio.Writer
のソースコードを確認すると Write
というメソッドを定義したインターフェースであることがわかります。
type Writer interface { Write(p []byte) (n int, err error) }
os.Stdout
を渡しているのに Fprintf
が問題なく動作するのはなぜでしょうか。 ここで os.Stdout
をのぞいてみます。
var ( Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin") Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout") Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr") )
os.Stdout
は os
パッケージ内の公開されている定数であり、右辺を見ると NewFile
を呼んでいます。
NewFile
の返り値は *File
型であるため os.Stdout
には *File
型の構造体が入っていることになります。
func (f *File) Write(b []byte) (n int, err error) { if f == nil { return 0, ErrInvalid } n, e := f.write(b) if n < 0 { n = 0 } if n != len(b) { err = io.ErrShortWrite } epipecheck(f, e) if e != nil { err = &PathError{"write", f.name, e} } return n, err }
上記のように File
構造体はWrite
メソッドを実装しているため、io.Writer
のインターフェースを満たすと判定され、引数として扱うことができます。
パッケージレイアウトの学び方について
書き方については、上記の例を挙げましたが、Go言語を学ぶなかでもう一つハマったのがパッケージレイアウトでした。
僕がパッケージレイアウトを学んだオススメの方法は、標準パッケージ群を読むことです。
上記はtimeパッケージのソースコードになりますが、ディレクトリ階層がなくフラットになっていることがわかります。
Go言語においてはこのようにパッケージ内のディレクトリを深くせず、フラットに実装するのが1つのパターンではあります。
ただ、Go言語においてのパッケージレイアウトについては語られることが多くなく、書かれている記事はこちらぐらいしか見つけることができませんでした。
View story at Medium.com
こちらの記事では以下のように書かれています。
Vendoring. Generics. These are seen as big issues in the Go community but there’s another issue that’s rarely mentioned — application package layout.
ベンダリングとジェネリクスはgoコミュニティの大きな問題ですが、もう一つの大きな問題であるapplication package layoutについてはほとんど言及されることがないようです。
僕は、パッケージレイアウトについては標準パッケージを参考にするという考え方をしています。
記事内で筆者はパッケージレイアウトについて提言をしてくれているのですが、
上記記事で紹介されているレイアウトが一般的になっているとは言い難い現状なのではないかと感じています。
少し抽象的になってしまいますが、import cycle
を避ける目的と依存が深くなるのを避けるために、フラットに実装するのが現時点では良いと考えています。
良いアプローチをお持ちの方がいれば教えていただきたいです。
#これからgoを学ぶ方へ
結論が抽象的な話を書いてしまいましたが、Go言語は薄く書けるし、書いていてとても楽しい言語です!
最後に、Go言語初学者が読んでおくと良い記事を紹介します。
https://talks.godoc.org/github.com/davecheney/introduction-to-go/introduction-to-go.slide#1
※Go言語の作成者であるDave cheneyさんがGo言語の構文やインストール方法について解説しています。
http://talks.godoc.org/github.com/davecheney/high-performance-go-workshop/high-performance-go-workshop.slide#1
※Dave Cheneyさんがベンチマークのとり方やプロファイリングについて解説している資料です
上記記事は日本語ではありませんが、サクっと探したWebの記事には書いていない内容が多くオススメです。
今年も残り短くなりましたが、皆様良いGolifeを!
そして、明日は森川さんです。お楽しみに!
エウレカでは、一緒に働いていただける方を絶賛募集中です。募集中の職種はこちらからご確認ください!皆様のエントリーをお待ちしております!