æè¿ã¯golangãã¢ããããããã¡ããã©Rebuild: 15: After Google Reader, DIY Blogging, The Go language (typester)ã§typesterãããgolangã«ã¤ãã¦è§¦ãã¦ããã®ãèãã¦ã試ãã«è§¦ã£ã¦ããããªããªã便å©ã§ãããã¨ãããã£ãã
golangã®å°è±¡ã¨ãã¦ã¯
- go getãgo runã«go buildãããã¦go testã便å©
- go fmtã®ãããªã³ã¼ãæ´å½¢ãã¼ã«ãã¤ãã¦ããã®ã¯å¬ãã
- (ãã ãã¤ã³ãã³ãããã¼ãã¿ããªã®ã¯ã¡ãã£ã¨æ代é ããªæ°ããã)
- æ¨æºpackageãå å®ãã¦ããã®ãé ¼ããã
- golangã®ãã¹ã³ãããã£ã©ã¯ã¿ã¼ã§ããGopherããããã
- (Gopher人形欲ãã)
ã¨ãã£ãæãã
âãããã
golangã®å
¥éã¨ãããã¨ã§ãskkservãå®è£
ãã¦ã¿ããskkservã¨ããã®ã¯ãã»ã¨ãã©ã®æ¹ã使ã£ã¦ããã§ãããSKK(æ¥æ¬èªå
¥åã·ã¹ãã )ã®è¾æ¸ãµã¼ãã®ãã¨ã§ãããã·ã³ãã«ãªãããã³ã«ãªã®ã§å®è£
ã¯å®¹æã§ãããããé¡æã¨ãã¦è¯ãããã ã
以ä¸ã¡ã¢æ¸ãã
GitHub - akiym/go-skkserv: Lightweight skkserv implementation for golang
packageãä½æ
How to Write Go Code - The Go Programming Languageãåèã«ãã¦ãpackageãä½æãã¦ã¿ããããã§æ³¨æãããã®ã¯ã$GOPATH以ä¸ã«packageãä½æããã¨ãããã¨ã
% mkdir -p $GOPATH/src/github.com/akiym/go-skkserv
ã¨ãããããã£ããã¨skkserv.goã«å¦çãæ¸ãã¦ããã
package skkserv import ( "bufio" "log" "net" ) const SkkServVersion = "0.0.1" type Handler interface { Request(text string) ([]string, error) } type SKKServ struct { Port string Handler Handler } func NewServer(port string, handler Handler) *SKKServ { server := &SKKServ{ Port: port, Handler: handler, } return server } func (s *SKKServ) Run() { ln, err := net.Listen("tcp", s.Port) if err != nil { log.Fatal(err) } for { conn, err := ln.Accept() if err != nil { continue } go s.handleConnection(conn) } } func (s *SKKServ) handleConnection(conn net.Conn) { defer conn.Close() reader := bufio.NewReader(conn) for { c, err := reader.ReadByte() if err != nil { return } switch c { case '0': return // end of connection case '1': buf, err := reader.ReadBytes(' ') if err != nil { return } s.serverRequest(conn, buf) case '2': s.serverVersion(conn) case '3': s.serverHost(conn) } } }
åãã¡ã½ãã
golangã¯ã©ã®ãããªè¨èªãªã®ããç¥ãããã«ãã¾ãã¯åã¨ã¡ã½ããã«ã¤ãã¦èª¿ã¹ã¦ã¿ããgolangã¯åã«å¯¾ãã¦ã¡ã½ãããçããããããã¦ã¡ã½ããåã大æåã§å§ãããã¨ã§ãpackageã®å¤ããå¼ã³åºããããã«ãªã(ã¨ã¯ã¹ãã¼ãããã)ãåºæ¬ã¯ä»¥ä¸ã
åºæ¬çãªå½¢:
type SKKServ struct { Port string Handler Handler } func NewServer(port string, handler Handler) *SKKServ { server := &SKKServ{ Port: port, Handler: handler, } return server }
ããã ãã§NewServerã¨ããã¡ã½ãããå®ç¾©ãããã¨ãã§ããã
å¥ã«ã¡ã½ãããçãããã¨ãã§ããã®ã¯structã ãã§ã¯ãªãããåã«å¯¾ãã¦ãã§ããããããã£ã¦stringã«å¯¾ãã¦ãåããããªãã¨ãã§ããã
package main import ( "fmt" ) type MyString string func (m MyString) Censor() string { s := make([]byte, len(m)) for i := 0; i < len(m); i++ { switch c := m[i]; c { case 'u': s[i] = '*' default: s[i] = c } } return string(s) } func main() { var foo MyString = "fuck" fmt.Println(foo.Censor()) }
ããã§æ³¨æãããã®ã¯stringãã®ãã®ã«å¯¾ãã¦ãã¡ã½ãããçãããã¨ã¯ã§ããªãã¨ãããã¨ãå®éã«ãã£ã¦ã¿ã¦ã
cannot define new methods on non-local type string
ã¨è¨ããã¦ãã¾ãã
ã¨ã©ã¼ãã³ããªã³ã°ãdefer
golangã«ã¯ä¸è¬çãªããã°ã©ãã³ã°è¨èªã§ããªãã¿ã®ãä¾å¤ãããªããããã代ããã«ãæ»ãå¤ã¨ãã¦errorãè¿ããã¨ã§ã¨ã©ã¼ãã³ããªã³ã°ãããå½¢å¼ã«ãªã£ã¦ããã
(æ¬è³ªã¯panicãrecoverã¨ããä»çµã¿ã ããããã§ã¯è§¦ããªã)
ä¾ãã°ããã®ããã«ã¨ã©ã¼ãã³ããªã³ã°ãã§ããã
c, err := reader.ReadByte() if err != nil { return }
ããããããã§æ°ã«ãããã®ã¯ãã¡ã¤ã«ãã£ã¹ã¯ãªãã¿ãã¯ãã¼ãºå¿ è¦ãããã¨ãããã¨ã ãerrorãè¿ã£ã¦ããã¨ãã«ãã¡ãã¡ã¯ãã¼ãºããã®ã¯å¤§å¤ã ã
c, err := reader.ReadByte() if err != nil { conn.Close() return } // ... if err != nil { conn.Close() return } // ...
ãªãã¦æ¸ãã¦ãããæ¥ãæ®ãã¦ãã¾ããtry-catch-finallyã§ããã¨ããã®finallyã®å¦çãæ¸ããããããã§deferã¨ããä»çµã¿ãç¨æããã¦ãããdeferãå©ç¨ãããã¨ã§ãreturnããç´åã«ç¹å®ã®å¦çãå®è¡ãããã¨ãã§ããã
defer conn.Close()
ãããããdeferã§ã¯ãã¼ãºããå¦çãæ¸ãã¦ããã°ããã¨ã¯æ°ã«ããå¿
è¦ã¯ãªããNO MORE æ©ã¿ç¡ç¨ã ã
golangã®ã¨ã©ã¼å¦çã¯ã»ãã®è¨èªã«æ
£ãã¦ãã身ã¨ãã¦ã¯æ±ãã«ããããã«æããããããããã®å¦çã¯å²ã¨æ¸ããããæ°ããã(å°ã貧弱ãããããªããã©)ã
åè: Defer, Panic, and Recover - The Go Blog
interface
ä»åã®å ´åããªã¯ã¨ã¹ããå¦çããhandlerãå®ç¾©ã§ãããããªè¨è¨ã«ããããããã§interfaceã¨ããä»çµã¿ãå©ç¨ããã
ãã®ããã«æ¸ãã¦ãããã¨ã§ãRequest()ã¨ããã¡ã½ãããå®è£
ããã¦ãããã¨ãæ示ãããã¨ãã§ããã
type Handler interface { Request(text string) ([]string, error) }
ãããã¾ãé¢ç½ãã¦ãå¤é¨ããã©ãå©ç¨ããã®ãã¨ããã¨:
type GoogleIMESKK struct{} func (s *GoogleIMESKK) Request(text string) ([]string, error) { words, err := Transliterate(text) if err != nil { return nil, err } return words, nil } func main() { var server = skkserv.NewServer(":55100", &GoogleIMESKK{}) server.Run() }
skkserv.NewServer()ã¯Handlerãåãåãããã«ãã¦ããã®ã§ãããã«Request()ãå®è£
ããåãã¤ã£ããã ãã
ããã¯interfaceã®ã»ãã®ä¸é¨ã§ãããªãã詳ãããã¨ã¯Go の interface 設計 - Block Rockin’ Codesã«æ¸ãã¦ããã
interfaceå
interfaceåã¯ã©ããªåã§ãåãåãããinterfaceåãå©ç¨ããå ·ä½ä¾ã¨ãã¦ã¯ãJSONã®ãã¼ã¹ããã:
dec := json.NewDecoder(resp.Body) var w [][]interface{} if err := dec.Decode(&w); err != nil { return nil, err } for _, v := range w[0][1].([]interface{}) { word := v.(string) result, ok := enc.ConvertStringOK(word) if ok { words = append(words, result) } }
interfaceåã§ã¢ãµã¼ã·ã§ã³ãã¦ãstringã«å½ã¦ç´ãããããããã§ãã¦ããã
ãã¹ããæ¸ã
ããã¾ã§skkserv.goãæ¸ãã¦ãããããã¹ãã¯skkserv_test.goã«æ¸ãã¦ãããè¦ãã°ãããã¨æãã*_test.go
ã¨ããååã®ãã¡ã¤ã«ããã¹ãã³ã¼ãã«ãªãããã¨ã¯import "testing"
ãã¦ã"Test"ã§å§ã¾ãã¡ã½ãããå®ç¾©ãã¦ããã°ãgo testã§ãã¹ããèµ°ããããã¨ãã§ããã
func TestRequest(t *testing.T) { server := NewServer(":55100", &TestHandler{}) go server.Run() // ...
ã¾ã¨ã
å°ãéã«ãªã£ãããã¨ããããgolangã§skkservãå®è£
ãããã¨ãã§ããã
ããã«ããã»ã¨ãã©ã®ãã¨ã¯golang.orgãè¦ãã°æ¸ãã¦ãããæ¥æ¬èªã®æ
å ±ãgolang.jpã«è©³ããæ¸ãã¦ããã®ã§å¿é
ã¯ãããªãã
ã¨ããããå°ã触ã£ã¦ã¿ãã ãã ã£ããgolangã¯ç´ æ´ãããè¨èªã ã¨æã£ããä»å¾ã使ã£ã¦ãããã