Goらしいコードの書き方(ミニ)

Go 1.6 Release Party

17 February 2016

鵜飼文敏

Fumitoshi Ukai

Google Software Engineer - Chrome Infra team

巻末付録「Goらしいコードの書き方」を書きました。

Go 1.6

言語仕様の変更 -> なし!

Goらしいコードの書き方は基本的にかわっていない。

Effective Go

Go is a new language. Although it borrows ideas from existing languages, it has unusual properties that make effective Go programs different in character from programs written in its relatives. A straightforward translation of a C++ or Java program into Go is unlikely to produce a satisfactory result -- Java programs are written in Java, not Go. On the other hand, thinking about the problem from a Go perspective could produce a successful but quite different program. In other words, to write Go well, it's important to understand its properties and idioms. It's also important to know the established conventions for programming in Go, such as naming, formatting, program construction, and so on, so that programs you write will be easy for other Go programmers to understand.

This document gives tips for writing clear, idiomatic Go code.

Effective Go - History

go spec (2008/05/02)
Effective Go first commit

commit 94439982b62dee7085aae289e4a6643debd69255
Author: Russ Cox <rsc@golang.org>
Date:   Thu Jun 25 09:38:35 2009 -0700

  Effective Go; draft

Until public release (2009/11/10): 36
go1 (2012/03/28): 81
go1.1 (2013/05/13): 26
go1.2 (2013/11/29): 12
go1.3 (2014/06/19): 9
go1.4 (2014/12/11): 2
go1.5 (2015/08/19): 5
go1.6 (2016/02/17?): 0

Today's topic

Goらしいコードを書く時のポイント

interface

パッケージのAPIとしてinterfaceを定義?

Goのインタフェースはとても便利で、実装の詳細を特定することなしにAPIを定義できます。
パッケージの基本的な構成要素について、可能な箇所では常にインタフェースとして定義しておくようにしましょう。
そうすれば、後で多くのメリットを期待できます。
Go言語によるWebアプリケーション開発。pp.21 1.4.1.1 インタフェース

パッケージのAPIとinterface

利用しやすいAPIを提供する -> yes!
Goのインタフェースはとても便利 -> yes!

実装の詳細を特定することなしにAPIを定義できる
-> Javaのinterfaceとかもそうでは?
Goのinterfaceが便利なところは、 あらかじめ定義しておく必要がない ところ

可能な箇所では常にインタフェースとして定義しておくように
-> Goではinterfaceは必要になった時に定義すればよい

Goのinterface

APIの実装側

io.Reader       Read([]byte) (int, error)
fmt.Stringer    String()     string

APIの利用側

type ReadCloser interface {
    Reader
    Closer
}

concrete type vs interface

concrete type

var mu sync.Mutex
var buf bytes.Buffer

interface

var r io.Reader
r = &buf

chan

goroutineとchan

コンカレントに動作するプログラムが簡単に書ける

とはいっても、正しく書くのはまだ難しい

chanを使う時に注意すべき点

chan receiverがいないのでchanにsendするところでブロック

非同期 vs 同期

非同期が簡単にできるといっても同期のほうが理解しやすい
非同期APIより同期API

package bufio
type Scanner
  func (s *Scanner) Scan() bool
  func (s *Scanner) Bytes() []byte
  func (s *Scanner) Err() error

package filepath
  func Walk(root string, walkFn WalkFunc) error
  type WalkFunc func(path string, info io.FileInfo, err error) error

chanをpackageを越えてあまり使わない
非同期にするにはAPIを使う側がgoroutine+chanで制御する
同期APIを実現するために必要なら実装内部でgoroutine+chanを使う

まとめ

They're fun to play with, but don't overuse these ideas.

Always use the right tool for the job.

by Rob Pike, Go Concurrenty Pattern

Thank you

鵜飼文敏

Fumitoshi Ukai

Google Software Engineer - Chrome Infra team

Use the left and right arrow keys or click the left and right edges of the page to navigate between slides.
(Press 'H' or navigate to hide this message.)