More Related Content Similar to メルカリ・ソウゾウでは どうGoを活用しているのか? (20) More from Takuya Ueda (10) メルカリ・ソウゾウでは どうGoを活用しているのか?1. メルカリ・ソウゾウでは
どうGoを活用しているのか?
The Go gopher was designed by Renee French.
The gopher stickers was made by Takuya Ueda.
Licensed under the Creative Commons 3.0
Attributions license. 1
2017/07/22(土)
@会津大Go勉強会
3. ソウゾウ エキスパートチーム
技術をアウトプットするところに技術は集まる
■ エキスパートチームとは?
● 50%以上の時間を技術コミュニケーションへの貢献に充てる
■ エキスパートチームの役割
● 社内に新しい技術を取り取り込む
● 社外のコミュニティなどを通じて社会へ還元する
■ エキスパートチームの活動
● カンファレンス・勉強会の開催/運営
● 対外的な講演活動
● 執筆、雑誌への寄稿、インタビュー
● 社内外での担当技術の普及推進
3
@tenntenn
担当:Go・GCP
@mhidaka
担当:Android
メンバー
6. アジェンダ
● Goを知る
○ Goの特徴
○ Goのドキュメントとコミュニティ
● メルカリ・ソウゾウにおけるGoの活用事例
○ Gaurun
○ go-httpdoc
○ メルカリ アッテ
○ メルカリ カウル
○ バナーツール
● Goの開発ノウハウ
○ インタフェースと抽象化
○ Goとテスト
○ エラー処理
6
9. Goの特徴 − シングルバイナリ・クロスコンパイル −
■ 環境変数のGOOSとGOARCHを指定する
開発環境とは違うOSやアーキテクチャ向けに
クロスコンパイルできる
9
シングルバイナリになるので
動作環境を用意しなくてよい
# Windows(32ビット)向けにコンパイル
$ GOOS=windows GOARCH=386 go build
# Linux(64ビット)向けにコンパイル
$ GOOS=linux GOARCH=amd64 go build
※ go build はGoのソースコードをビルドするコマンド
10. Goの特徴 − 強力でシンプルな言語設計と文法 −
■ スクリプト言語の書きやすさ
● 冗長な記述は必要ない
■ 型のある言語の厳密さ
● 曖昧な記述はできない
■ 考えられたシンプルさ
● 機能を増やすことで言語を拡張していくこと
はしない
10
Goに入ってはGoに従え
= 言語の思想を理解しよう
11. Goの特徴 − 並行プログラミング −
■ ゴールーチン
● 軽量なスレッドに近いもの
● goキーワードをつけて関数呼び出し
■ チャネル
● ゴールーチン間のデータのやり取り
● 安全にデータをやり取りできる
11
チャネル
ゴールーチン
A
ゴールーチン
B
データ
データ
// 関数fを別のゴールーチンで呼び出す
go f()
12. Goの特徴 − 豊富な標準ライブラリ −
■ 標準ライブラリ一覧
https://golang.org/pkg/
12
net/http HTTPサーバなど
archive, compress zipやgzipなど
crypto 暗号化
encoding JSON, XML, CSVなど
html/template HTMLテンプレート
os, path/filepath ファイル操作など
13. Goの特徴 − 周辺ツールの充実 −
■ go tool として標準/準標準で提供
■ サードパーティ製のツールも充実
■ IDEによらない独立したツールとして提供
13
go build ビルドを行うコマンド
go test
xxxx_test.goに書かれたテスト
コードの実行
go doc, godoc ドキュメント生成
gofmt, goimports コードフォーマッター
golint コードチェッカー、リンター
gocode コード補完
15. コミュニティに参加する
■ Goビギナーズ
● https://go-beginners.connpass.com/
● 初心者向けのGoのコミュニティ
■ golang.tokyo
● https://golangtokyo.connpass.com/
● Goの採用企業間で情報共有をするコミュニティ
■ Go Conference
● https://gocon.connpass.com/
● 日本最大のGoのカンファレンス
■ Gophers Slack
● https://invite.slack.golangbridge.org/
● 世界中のGopher(Goのユーザ)が集まる
15
32. コードの書式を揃える
■ gofmt
● 読み方:ごーふむと
● 標準のフォーマッタ
● 絶対に使う
● -s オプションで冗長な書き方をシンプルにできる
■ goimports
● import文を追加/削除してくれる
● 未使用パッケージのimportはエラーなので必須
● フォーマットもかける
● -s オプションがない
32
33. コードの品質を保つ
■ go vet
● バグである可能性の高いものを検出する
■ golint
● コーディングスタイルをチェックする
■ errcheck
● エラー処理が適切に行われているかチェックする
■ その他のツール
● http://haya14busa.com/ci-for-go-in-end-of-2016/
33
34. デバッグ
■ GDB
● https://golang.org/doc/gdb
● 有名な古き良きデバッガ
● Go自体にカスタマイズされてるわけではない
■ Delve
● https://github.com/derekparker/delve
● Go専用のデバッガ
● ゴルーチンやチャネルにも対応
■ panicデバッグ
● panicを使ってデバッグ
● スタックトレースが出るので便利
34
38. 組み込み型
■ 組み込み型
● int,int8,int16,int32,int64
● uint,uint8,uint16,uint32,uint64
● uintptr,byte,rune
● float32,float64
● complex64,complex128
● string
● bool
● error
38
39. // 組み込み型を基にする
type Int int
// 他のパッケージの型を基にする
type MyWriter io.Writer
// 型リテラルに基にする
type Person struct {
Name string
}
typeを使った型の作成
type <型名> <型リテラル>|<型名>
39
intとIntは別の型として扱われる
41. 型エイリアス(Go 1.9以上)
■
41
■ 型のエイリアスを定義できる
● 完全に同じ型
● キャスト不要
● エイリアスの方ではメソッド定義はできない
type Applicant = http.Client
■ %Tは同じ元の型名を出す
type Applicant = http.Client
func main() {
fmt.Printf("%T", Applicant{})
}
http.Client
42. type Hex int
func (h Hex) String() string {
return fmt.Sprintf("%x", int(h))
}
メソッドとレシーバ
type で定義した型はメソッドのレシーバにできる
42
Playgroundで動かす
// 100をHex型として代入
var hex Hex = 100
// Stringメソッドを呼び出す
fmt.Println(hex.String())
48. interface{}
■ empty interface
● メソッドリストが空なインタフェース
● つまりどの型の値も実装していることになる
● JavaのObject型のような使い方ができる
48
var v interface{}
v = 100
v = "hoge"
Playgroundで動かす
52. 埋め込みの特徴
■ 型リテラルでなければ埋め込められる
● typeで定義したものや組み込み型
● インタフェースも埋め込められる
■ インタフェースの実装
埋め込んだ値のメソッドもカウント
52
// Stringerを実装
type Hex int
func (h Hex) String() string {
return fmt.Sprintf("%x", int(h))
}
// Hex2もStringerを実装
type Hex2 struct {Hex}
Playgroundで動かす
type Stringer interface {
String() string
}
53. インタフェースと埋め込み
■ 既存のインタフェースの振る舞いを変える
53
type Hoge interface{M();N()}
type fuga struct {Hoge}
func (f fuga) M() {
fmt.Println("Hi")
f.Hoge.M() // 元のメソッドを呼ぶ
}
func HiHoge(h Hoge) Hoge {
return fuga{h} // 構造体作る
}
Mの振る舞いを変える
参考:インタフェースの実装パターン
60. go testのオプション(一部)
■ -v
● 詳細を表示する
■ -cpu
● 実行する並列度を指定する
● 複数のコアを使ったテストができる
■ -race
● データの競合が起きないかテストする
■ -cover
● カバレッジを取得する
61. testingパッケージ
■ testを行うため機能を提供するパッケージ
*testing.T型のメソッド使う。
type Hex int
func (h Hex) String() string {
return fmt.Sprintf("%x", int(h))
}
61
package mypkg_test
import "testing"
func TestHex_String(t *testing.T) {
expect := "a"
actual := mypkg.Hex(10).String()
if actual != expect {
t.Errorf(`expect="%s" actual="%s"`, expect, actual)
}
}
65. テーブル駆動テスト
■ テスト対象のデータを羅列してテストする
65
参考:https://github.com/golang/go/wiki/TableDrivenTests
var flagtests = []struct {
in string
out string
}{
{"%a", "[%a]"},
{"%-a", "[%-a]"},
{"%+a", "[%+a]"},
{"%#a", "[%#a]"},
{"% a", "[% a]"},
}
func TestFlagParser(t *testing.T) {
var flagprinter flagPrinter
for _, tt := range flagtests {
s := Sprintf(tt.in, &flagprinter)
if s != tt.out {
t.Errorf("Sprintf(%q, &flagprinter) => %q, want %q", tt.in, s, tt.out)
}
}
}
66. ■ テストカバレッジの分析
$ go test -coverprofile=profile fmt
$ head profile
mode: set
fmt/format.go:30.13,31.29 1 1
fmt/format.go:31.29,34.3 2 1
fmt/format.go:67.28,69.2 1 1
fmt/format.go:71.33,74.2 2 1
fmt/format.go:77.85,80.11 3 1
fmt/format.go:84.2,85.11 2 1
fmt/format.go:96.2,96.8 1 1
fmt/format.go:80.11,83.3 2 0
fmt/format.go:85.11,86.21 1 1
coverprofile
パッケージ名
テストできるのは
パッケージごと
66
72. 環境変数を使う
■ 環境変数を使って切り替える
● os.Getenvで取得できる
● CIでテストを走らせるときに便利
● DBの接続先など環境に依存する値を保存する
■ github.com/jinzhu/configorを使う
72
var Config = struct {
DB string `env:"DB"`
}{}
func main() {
configor.Load(&Config, "config.yml")
fmt.Printf("config: %#v", Config)
}
77. エラーに文脈を持たせる
■ github.com/pkg/errorsを使う
● File Not Foundとかでは分かりづらい
● 何をしようとした時にエラーが起きたか知りたい
● どんなパラメータだったのか知りたい
● errors.Wrapを使うとエラーをラップできる
● errors.Causeを使うと元のエラーが取得できる
77
if err := f(s); err != nil {
return errors.Wrapf(err, “f() with %s”, s)
}
79. まとめ
● Goを知る
○ Goの特徴
○ Goのドキュメントとコミュニティ
● メルカリ・ソウゾウにおけるGoの活用事例
○ Gaurun
○ go-httpdoc
○ メルカリ アッテ
○ メルカリ カウル
○ バナーツール
● Goの開発ノウハウ
○ インタフェースと抽象化
○ Goとテスト
○ エラー処理
79