View
2.960
Download
1
Embed Size (px)
DESCRIPTION
プログラミング言語 Go は Google が 2009 年秋にオープンソースで公開した新しいプログラミング言語です。C や C++ のようなコンパイル言語の良さをもちつつ、Python のような動的言語でのプログラムの書き易さを兼ねそなえた特徴をもっています。クラスを使わないオブジェクト指向の言語で、コンカレントに実行するための仕組みもそなえています。 プログラミングをより速く、より生産的に、そしてより楽しくしてくれる新しいプログラミング言語 Go について説明します。
Citation preview
Revised v4Presenter
プログラミング言語Go鵜飼文敏 / Google Software Engineer
今日の内容
godentaku - Goで作った電卓
入出力の基本
sliceの使い方
型システム: struct, pointer, interface
goパッケージ
ローカル・サードパーティ
使い方・作り方
Go言語とは?
新しいシステムプログラミング言語Googleが設計・開発
Rob Pike, Ken Thompson, Robert Griesemer, Russ Cox, Ian Lance Taylerなど2009/11/10にオープンソースとして公開
http://golang.orgコントリビュータ: 125名 (2010/09)
Go言語の特徴
静的型付け・型安全ダックタイピング
短いコンパイル時間大規模プログラミング可能
ネットワーキングマルチコア
主流プログラミング言語C++, Java
ライトウェイト言語Python, Rubyなど
What's new?DevFest (2010/3)から
complex型x := m[k] がpanicしなくなった。s[0:n] が s[:n]にpanic(), recover()goinstallコマンドgomakeコマンド ($GOOS, $GOARCH, ...)goprofコマンドGo dashboardnew package
crypto/ripemd160, hash/crc64, crypto/rand, utf16, nntp, mime/multipart, html, net/textproto, net/dict, crypto/ocsp, runtime/pprof, http/pprof, cmath, rpc/jsonrpc, go/typecheckeronce -> sync.Once()
The Go Playground
今日のお題:電卓
$ ./godentaku>1+2*37>y=x*x + (a+b)*x + a*b(((x * x) + ((a + b) * x)) + (a * b))>a=11>b=22>y(((x * x) + (3 * x)) + 2)>x=55>y42
godentaku仕様
式を入力して、それを評価して出力四則演算変数
言語の基本機能で実装 パッケージをあまり使わない (fmt, os, bufioのみ)
godentaku入力
標準入力から一行づつバイト列を読み取る式を解析
バイト列を抽象構文木に変換式を評価
抽象構文木を解釈・実行結果を出力
結果を文字列にして標準出力に繰り返す
入力: bufiohttp://golang.org/pkg/bufio/#Reader.ReadBytes
�func (*Reader) ReadBytesfunc (b *Reader) ReadBytes(delim byte) (line []byte, err os.Error)
ReadBytes reads until the first occurrence of delim in the input, returning a string containing the data up to and including the delimiter. If ReadBytes encounters an error before finding a delimiter, it returns the data read before the error and the error itself (often os.EOF). ReadBytes returns err != nil if and only if line does not end in delim.
import ("bufio"; "os")
in := bufio.NewReader(os.Stdin)
line, err := in.ReadBytes('\n')if err != nil { ... }
出力: fmthttp://golang.org/pkg/fmt/#Printf
func Printffunc Printf(format string, a ...interface{}) (n int, errno os.Error)
Printf formats according to a format specifier and writes to standard output. It returns the number of bytes written and any write error encountered.
import "fmt"
fmt.Printf("> ")
fmt.Printf("%d", i)
fmt.Printf("%#v", v)
コンパイル&実行% cat main.gopackage mainimport ("bufio"; "fmt"; "os")func main() { in := bufio.NewReader(os.Stdin) for { line, err := in.ReadBytes('\n') if err != nil { break } fmt.Println(string(line)) }}% 6g main.go # 8g main.go% 6l main.6 # 8l main.8% ./6.out # ./8.out
Read-eval-print looppackage mainimport ("bufio"; "fmt"; "os")func readEvalPrint(in *bufio.Reader, env *Env) os.Error
func main() { in := bufio.NewReader(os.Stdin) env := NewEnv() // for variable table for { err := readEvalPrint(in, env) if err != nil { break } }}
Read-eval-print loopfunc readEvalPrint(in *bufio.Reader, env *Env) os.Error { fmt.Printf("> ") line, err := in.ReadBytes('\n') if err != nil { return err } ast, nbuf := Read(line) v := Eval(ast, env) fmt.Println(Print(v, env)) return nil}
Read: getNumfunc getNum(buf []byte) (n int, nbuf []byte) { n := digitVal(buf[0]) nbuf = buf[1:] for len(nbuf) > 0 { if d := digitVal(nbuf[0]); d >= 0 { n = n * 10 + d } else { break } nbuf = nbuf[1:] } return n, nbuf}func digitVal(b byte) int { if b >= '0' && b <= '9' { return int(b - '0') // int型に変換 } else { return -1 }}
slicesliceは配列につかうポインタ
Read: getSymbolfunc getSymbol(buf []byte) (sym string, nbuf []byte) { var i int for i = 0; i < len(buf); i++ { if !isAlpha(buf[i]) && !isDigit(buf[i]) { break } } return string(buf[0:i]), buf[i:]}
抽象構文木
再帰降下パーザ
// stmt := expr | sym '=' exprfunc parseStatement(b []byte) (stmt Ast, n []byte)
// expr := ['+'|'-'] term { ['+'|'-'] term }func parseExpression(b []byte) (expr Ast, n []byte)
// term := factor { ['*'|'/'] factor }func parseTerm(b []byte) (term Ast, n []byte)
// factor := num | symbol | '(' expr ')'func parseFactor(b []byte) (factor Ast, n []byte)
interface: Asttype Ast interface { String() string Eval(env* Env) Ast}
Ast型の変数に代入できるのは、これらのメソッドが定義されている型のオブジェクト
Astにいれて使う型はこれらのメソッドを定義Astを使うほうは、これらのメソッドが利用可能
named type: Numtype Num intfunc (n Num) String() string { return fmt.Sprintf("%d", int(n))}func (n Num) Eval(env *Env) Ast { return n }
func getNum(b []byte) (num Num, nbuf []byte) { ... return Num(n), nbuf}
NumはAst型
named type: Symboltype Symbol stringfunc (s Symbol) String() string { return string(s)}func (s Symbol) Eval(env *Env) Ast { ... }
SymbolもAst型
map: variable tabletype Env struct { Var map[string]Ast; .. }func NewEnv() *Env { env := new(Env) env.Var = make(map[string]Ast) return env}func Set(env* Env, key string, n int) { env.Var[key] = Num(n)}func envValue(env* Env, key string) (n int, ok bool) { if v, found := env.Var[key]; found { .. } return 0, false}
structとポインタtype Point struct { x, y int }type Rect struct { min, max Point }
type Rect2 struct { min, max *Point }
BinOptype Ast interface { .. }type BinOp struct { Op byte; Left, Right Ast }func (b BinOp) String() string {..}func (b BinOp) Eval(env *Env) Ast { .. }func parseExpression(b []byte) (expr Ast, n []byte) { expr, n = parseTerm(b) for n[0] == '+' || n[0] == '-' { op := n[0]; var term Ast term, n = parseTerm(n[1:]) expr = BinOp{Op: op, Left:expr, Right:term} } return expr, n}
BinOpもAst型
interface: memory layout
interface type-switchfunc parseStatement(b []byte) (stmt Ast, n []byte) { stmt, n = parseExpression(b) if n[0] == '=' { if sym, ok := stmt.(Symbol); ok { var expr Ast expr, n = parseExpression(n[1:]) stmt = AssignOp{Var:sym, Expr:expr} } else { /* 例外処理 */ } } return stmt, n}
例外処理func readEvalPrint(in *bufio.Reader, env *Env) os.Error { defer func() { if x := recover(); x != nil { ... } }() .. Read(line) ..}func Read(b []byte) (ast Ast, n[]byte) { return parseStatement(b)}func parseStatement(b []byte) (stmt Ast, n []byte) { ... if sym, ok := stmt.(Symbol); ok { .. } else { panic("lvalue is not symbol:" + stmt.String()); }}
いままでのまとめ入出力
bufiofmt
型システムint, string, ..slicemapstructポインタinterface
packageにする
1. ファイルを分割するメインのファイル (main.go)パッケージのファイル (godentaku.go)
2. メインのファイルimport に "./godentaku"godentaku.Read(line)
3. パッケージのファイルpackage godentaku大文字ではじまるシンボルがパブリック
packageのビルド
% 6g godentaku.go% 6g main.go # main.goとgodentaku.6を読む% lsgodentaku.6 godentaku.gomain.6 main.go% 6l main.6% ./6.out
packageディレクトリ% mkdir godentaku; mv godentaku.* godentaku/; cd godentaku% cat > Makefileinclude $(GOROOT)/src/Make.incTARG=godentaku # importでつかうパッケージパスGOFILES=\ godentaku.go\include $(GOROOT)/src/Make.pkg% gomake # コンパイルとリンク% gomake install # -> ${GOROOT}/pkg/${GOOS}_${GOARCH}/${TARG}.a
packageの公開
標準packageにコントリビュートcodereviewhttp://golang.org/doc/contribute.html
サードパーティpackageとして公開http://godashboard.appspot.com/package
サードパーティpackageの利用
インストール % goinstall goprotobuf.googlecode.com/hg/proto
利用する時 import "goprotobuf.googlecode.com/hg/proto"
data, err := proto.Marshal(obj)
googlecode - project hosting
googlecode - createProject
Mercurial
https://yourproj.googlecode.com/hg
hgrc% cat .hg/hgrc[paths]default = https://yourproj.googlecode.com/hg/[ui]username = Your Name <[email protected]>[auth]googlecode.prefix = yourproj.googlecode.com/hg/gogolecode.username = [email protected] = XXXXXgooglecode.schemes = https
publish package1. プロジェクトの作成2. hg clone3. hgrcの編集4. ファイルの追加
hg addMakefileの編集
TARGを import path5. hg commit6. hg push
本日のまとめ
Go言語を使って入出力の基本型システムの基本packageの使い方・作り方
googlecode project hostingで公開
今日やらなかったこと
並行処理: goroutineとchannelIota: enum的なものgoツール
godoc, gofmt, gotest, goyacc などcgo: Cコードを呼ぶgoパッケージの作成
標準パッケージの使い方などなど
May the Source be with You