Goã®åå¼·ãã¦ãã«Pythonã§æ¸ããCLIãGoã§æ¸ãç´ãã話
ããã«ã¡ã¯ã社ä¼äºº2ã¶æãçµéãããããã§ãã 社å ç ä¿®ãçµããé¨ç½²é å±ããã¦ã¯ã2é±éãéãã¾ãããæ¬å½ã«æ©ãw
ãã¦ãã¦ãé¨ç½²é å±ããã¦ããã»ã¨ãã©Rubyã°ã£ããæ¸ãã¦ãã¦Python触ã£ã¦ããªããã§ããæè¿Rustã¨Goã«èå³ãåºã¦ãã¾ãã¦ããã£ãããªã®ã§å°ãåã«æ¸ããCLIãGolangã§æ¸ãç´ãã¦Goãå¦ã¼ãã¨ããéèã§ãã
- åææ¡ä»¶
- ææ³ãå¦ã¶
- Range
- CLI ã®è¨è¨
- JSONã®èªã¿è¾¼ã¿ã¨è§£æ
- APIã«å®éã«æ¥ç¶
- CLIã®å®æ
- CircleCI 2.0ã使ã£ã¦ãã¹ããã
- ãã¹ãã«ãã¬ãã¸ã®è¨æ¸¬
- Windowsã§åä½ãä¿è¨¼ããããã«Appveyorã使ã
- ããã¾ã§ã§å½¹ã«ç«ã£ãè³æãææ³ãªã©
- çå
- ã¾ã¨ã
åææ¡ä»¶
- CLI ã¨ãã¦æ©è½ããã
- å¤é¨APIã«GETã§ãªã¯ã¨ã¹ããã¦è¿ã£ã¦ããJSONã¬ã¹ãã³ã¹ããã¼ã¹ãã¦ãå¿ è¦ãªå¤ãåãåºãã
ããæ¸ãã ãã ã¨2ã¤ãããããã¨ç¡ããæ¥½ãããã¨æãã¾ããããããã¾ãã¯è¡ãã¾ããã§ããã
ææ³ãå¦ã¶
ã¾ããGoã®ãã¼ã¿æ§é ã¨ææ³ãç¥ããªãã®ã§ãããå¦ã¶å¿ è¦ãããã¾ããã ã¨ããããå ¬å¼ã«ããA Tour of Goããã®ã¾ã¾èªã¿é²ãã¦ããã¾ãããPythonã§æ¸ãã¦ããã¨ãã¨æã ç°ãªãç¹ããã£ãã®ã§ããã ãã¡ã¢ãã¦ããã¾ãã(ã¨ã¯ããå ¬å¼ãèªãã°ããããã ãã©ã)
åºæ¬çã«ã¯ A Tour of Go ããã®ã¾ã¾èªã¿é²ãã¦ãããã®ã§ãããã å人çã«æ°ã«ãªã£ããã¨ãã¡ã¢ãæ®ãã¦ãããã¨æãè¨äºã«ãã¾ããã
é å
Pythonã ã¨ä½ãèããã« [ ]
ã«å¤ãæ¾ãè¾¼ãã ãã§ãããGolangã§ã¯é
åã®é·ãã1度決ãããå¤ãããã¨ã¯ã§ããªãããåãæ±ºã¾ã£ã¦ãã¾ãã
å®ç¾©ã®åºæ¬
var <夿°å> [é·ã]<å>
ã¾ãã2éãããã¾ãã1ã¤ã¯ var
ã§åã確å®ããã¦å®ç¾©ãããã®ãã¾ãã2çªãã®ããã«åæå¤ããã®ã¾ã¾æ±ºãæã¡ã§åæåãããã¨ãã§ãã¾ãã
var a [2]string a[0] = "Hello," a[1] = "world" primes := [6]int{2, 3, 5, 7, 11, 13}
ã¹ã©ã¤ã¹
é
åã¯åºå®é·ã®ãµã¤ãºã§ããã®ã«å¯¾ããã¹ã©ã¤ã¹ã¯å¯å¤é·ãµã¤ãºã§ãã容éãè¶³ããªããªãã¨èªåçã«é åãåºãã¦ããã¾ãã
çæã«ã¯ãã«ãã¤ã³é¢æ°ã® make
ã使ãã¾ãã
a := make([]int, 5)
ã¾ããã¹ã©ã¤ã¹ã«å¤ã追å ãããå ´å㯠append
ã¨ãã颿°ãç¨ãã¾ããappend
颿°ã¯ç¬¬1弿°ãå¤ã追å ãããã¹ã©ã¤ã¹ãå
¥ããæ®ãã®å¼æ°ã¯è¿½å ãããå¤ãå
¥ãã¾ãã
package main import "fmt" func main() { var s []int s = append(s, 0) printSlice(s) s = append(s, 1, 2, 3, 4, 5) printSlice(s) } func printSlice(s []int) { fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s) }
å®è¡çµæã¯ä»¥ä¸ã®ããã«ãªãã
len=1 cap=1 [0] len=6 cap=6 [0 1 2 3 4 5]
Pythonã§ã¯ã[1, 2].append(10)
ã®ããã«ãã¾ããGoã¯ãªãã¸ã§ã¯ãæåè¨èªã§ã¯ãªãå½ä»¤å½¢è¨èªãªã®ã§ãããªãã¾ãã
Range
Rangeã¯ã¯Pythonã§è¨ãã¨ããã® enumerate ã¨åãæåããã¦ããã¾ããé°å²æ°çã«ã¯ã¹ã©ã¤ã¹ã«ã¢ã¯ã»ã¹ããéã«ã¤ãã¬ã¼ã¿æä½ãã§ããããããã®ã§ãã
Pythonã§ãã®ãããªå¦çã¯
pow = [1, 2, 4, 8, 16, 32, 64, 128] for i, v in enumerate(pow): print("2**{i}={v}".format(i=i, v=v))
Golangã§ã¯ãã®ããã«æ¸ãã¾ãã
var pow = []int{1, 2, 4, 8, 16, 32, 64, 128} for i, v := range pow { fmt.Printf("2**%d=%d\n", i, v)
è¾æ¸
Pythonã§ã¯dictåãGolangã§ã¯Mapã¨ããã¾ããç¨èªã®éããªã®ã§è¦ãããããªãããã§ãã
ã¹ã©ã¤ã¹åæ§ã§ make
颿°ã§ãå®ç¾©ã§ãã¾ãã
Goã§ã¯mapã¯ãã¥ã¼ã¿ãã«ãªãã®ã§ããã®ã§ãæåã«mapãå®ç¾©ãã¦ãã¾ãã°å¤ãæ¿å ¥ãããããã¼ã«ããåç §ãåé¤ãå¯è½ã«ãªã£ã¦ãã¾ãã
package main import "fmt" func main() { m := make(map[string]int) // stringããã¼ãå¤ã¯int m["answer"] = 42 fmt.Println("The value: ", m["answer"]) // åå¾ m["answer"] = 28 fmt.Println("The value: ", m["answer"]) // 䏿¸ã delete(m, "answer") fmt.Println("The value: ", m["answer"]) // åé¤ v, ok := m["answer"] fmt.Println("The value: ", v, "Present?", ok) // åå¨ããã }
åé¤ããå¾ã«åç §ããã¨ä¾å¤çã¯çºçãããåæå¤ãå¤ããããã«ãªã£ã¦ãã¾ããã¾ã第2弿°ã§åå¨å¯å¦ãå¤å®ã§ãã¾ãã
Exercise: Maps
A Tour of Goã®ç·´ç¿åé¡ã¨ãã¦æåås
ã«å«ã¾ããåèªãæ°ãä¸ããããã°ã©ã ãæ¸ãã¾ããã
package main import ( "strings" "golang.org/x/tour/wc" ) func WordCount(s string) map[string]int { m := make(map[string]int) for _, key := range strings.Fields(s) { _, exist := m[key] if exist { m[key] += 1 } else { m[key] = 1 } } return m } func main() { wc.Test(WordCount) }
ã¡ãªã¿ã«å®è¡çµæã¯ãããªæãã«ãªãã¾ãã
$ go run aaa.go PASS f("I am learning Go!") = map[string]int{"I":1, "am":1, "learning":1, "Go!":1} PASS f("The quick brown fox jumped over the lazy dog.") = map[string]int{"jumped":1, "over":1, "lazy":1, "dog.":1, "The":1, "quick":1, "brown":1, "fox":1, "the":1} PASS f("I ate a donut. Then I ate another donut.") = map[string]int{"I":2, "ate":2, "a":1, "donut.":2, "Then":1, "another":1} PASS f("A man a plan a canal panama.") = map[string]int{"man":1, "a":2, "plan":1, "canal":1, "panama.":1, "A":1}
颿°
Golangã®é¢æ°ã«ã¯å¼æ°ã«é¢æ°ãä¸ãããã¨ãã§ãããã¨ãã話ã§ãããã¾ãGoã®é¢æ°ã¯ã¯ãã¼ã¸ã£ãããã§ãã
ä¾é¡ã¨ãã¦ãã£ããããæ°åãã¯ãã¼ã¸ã£ã使ã£ã¦æ¸ãã¦ã¿ã¾ããã
package main import "fmt" func fibonnacci() func() int { p, n := 0, 1 return func() int { p, n = n, p+n return n } } func main() { f := fibonnacci() for i := 0; i < 10; i++ { fmt.Println(f()) } }
ãããªæãã
ã¡ã½ãã
Goã«ã¯ã¯ã©ã¹ããªããããã¡ã½ããã¯åå¨ããªãã¯ãã§ããããã©ãåã«ã¡ã½ãããå®ç¾©ã§ããã¨ãã話ã¿ããã§ãããã®ã¨ãã¯func
ãã¼ã¯ã¼ãã¨ã¡ã½ããåã®éã«å¼æ°ãªã¹ããæ¸ãã¾ãããããããã¤ã³ã¿ã¼ã¬ã·ã¼ãã¼ã¨ããããã¤ã³ã¿ã¼ã¬ã·ã¼ãã¼ããªãã¨ãèªåã®åã«å®ç¾©ããã¡ã½ããã§å¤ãæ¸ãæãããã¨ãã§ãã¾ããã
ä¾ãã°A Tour of Goã®ã³ã¼ããæåãã¦èªåãªãã®è¨èã§ã¾ã¨ãã¾ãã
package main import "fmt" type Vertex struct { X, Y float64 } func (v *Vertex) Scale(f float64) { v.X = v.X * f v.Y = v.Y * f } func main() { v := Vertex{3, 4} v.Scale(10) fmt.Println(v) }
Scale
ã¯å Vertex
ã®ã¡ã½ããã§ã弿°ã«10ãä¸ããã¨çµæã¯æ¬¡ã®ããã«ãªãã¾ãã
{30 40}
ããã«å¯¾ãããã夿°ã¬ã·ã¼ãã¼ã¨ããå ´åãã¤ã¾ã
- func (v *Vertex) Scale(f float64) { + func (v Vertex) Scale(f float64) {
ã®ããã«æ¸ãã¨æ¬¡ã®ãããªçµæãå¾ããã¾ãã
{3 4}
ã¤ã¾ãã夿°ã¬ã·ã¼ãã¼ã®å ´åã¯å ã®Vertex夿°ã®ã³ãã¼ãæä½ãã¦ãããããå¼ã³åºãå ã®å¤ã¯å¤æ´ããã¾ããã
interface
æåå ¬å¼ããã¥ã¡ã³ããèªãã ã¨ãã¯å ¨ãæå³ãããããªãã£ãã®ã§ãããç°¡åã«è¨ãã¨èªåã§å¥½ããªåãæ±ºãããã¨ãã§ããã¿ããã
å¾ã JSONããããã³ã°ããéã«ããã使ãã¾ããã¾ããå¤åã§ãããThe empty interfaceããå ã¯èªãã§ãããã»ããããã¨æãã¾ãã
ãã®ä»
ä»åã¯ä½¿ãã¾ããã§ããããGo Routineçããã¡ãã¨åå¼·ãã¦ããã¨ä¸¦è¡å¦çãããéã«å½¹ç«ã¤ããããã¾ããã
ãã¦ãGoè¨èªã®å¤§ä½ã®å¦ç¿ã«Pythonã¨ã®æ¯è¼ãè¸ã¾ãã¦ãã£ã¦ãããããã ããã2æéç¨åº¦ãè¦ãã¾ãããããããã¯å®éã«CLIå½¢å¼ã®ããã¸ã§ã¯ããPythonããGoã«æ¸ãç´ãã¦ããã¾ãã
CLI ã®è¨è¨
ç§»æ¤åã®Pythonã®ã³ã¼ãã¯ãã¡ãã«ãªãã¾ãã
æåã¨ãã¦ã¯READMEã«æ¸ãã¦ããã¨ããã§ãããfactordb ã¨ããæ°åãæãã¤ããã¨ç´ å æ°åè§£ã®çµæãè¿ãã¦ããããµã¤ããããã¾ãã(ã¡ãªã¿ã«æ¯åº¦ç´ å æ°åè§£ãå®è¡ãã¦ããã®ã§ã¯ãªããDBã¨ããããã«ãã¼ã¿ãã¼ã¹ããæ¢ç¥ã®å¤ãè¿ãã¦ãããã ãã§ã) ä¾ãã°ã16ãªã 2 ^ 4 ã®ããã«è¿ãã¦ããã¾ããCLIã§ã¯æ¬¡ã®ããã«ä½¿ãã¾ãã
$ factordb 16 2 2 2 2
ã¾ãããªãã·ã§ã³ã« --json
ãã¤ããã¨APIããã®è¿ãå¤ã使ããããJSONã®å½¢å¼ã«å¤å½¢ãã¦åºåãã¦ããããã¤ããå°ã詳細ãåºãã¦ããã¾ãã
$ factordb --json 16 {"id": "https://factordb.com/?id=2", "status": "FF", "factors": [2, 2, 2, 2]}
Golangã§å®éã«CLIã使ããã«ãããã
ã®ã³ã¼ããåèã«æ¸ãã¾ããã
æåã«âãåèã«ãªãã·ã§ã³ãå¼ãåã£ã¦é©å½ã«CLIã£ã½ãæåãããã³ã¼ããæ¸ãã¾ããã
package main import ( "fmt" "os" "github.com/codegangsta/cli" ) func main() { app := cli.NewApp() app.Name = "factordb" app.Usage = "The CLI for factordb.com" app.Version = "0.0.1" // Global option app.Flags = []cli.Flag{ // --json cli.BoolFlag{ Name: "json", Usage: "Return response formated JSON", }, } app.Action = callAction app.Run(os.Args) } func callAction(c *cli.Context) error { var isJson = c.GlobalBool("json") if isJson { fmt.Println("Response json type") } var paramFirst = "" if len(c.Args()) > 0 { paramFirst = c.Args().First() } fmt.Printf("Hi, I am receiving the number %s\n", paramFirst) return nil }
https://github.com/ryosan-470/factordb-go/blob/acd2fbb6c5e9bf7f84e7c2bd7e90001c3337b012/cli.go
âã®ã³ã¼ãã¯ããã--json
ãã¤ãã¦ããã¨æ¨æºåºåã« Response json type
ã¨ããã¨ã¯å¼æ°ãHi, I am receiving the number 16
ã¿ãããªå½¢ã§åºåãã¦ãããããã°ã©ã ã§ãããã®ã¾ã¾ã©ã®ç°å¢ã§ãåãããã¨æãã¾ãã
JSONã®èªã¿è¾¼ã¿ã¨è§£æ
次ã«ãJSONãèªã¿è¾¼ãã§Golangã®æ§é ä½ã«ç½®ãæãã¾ããGolangã§ã¯
ãªã©ã«ããããã«ãjson.Unmarshal
ãªã©ã§è§£æãã¦æ§é ä½ã«ç½®ãæãããã¨ã§ã³ã¼ãå
ã§ãããªã«æ±ããã¨ãã§ããã¿ããã§ãããããFactorDBã®APIã«ã¢ã¯ã»ã¹ãã¦ã¿ãã°ãããã¾ããè¿ã£ã¦ããJSONã¯ãä¸è¾ã«ããã¬ã¤ãªãã®ã¨ã¯ããã¾ããã
$ http http://factordb.com/api\?query\=10 HTTP/1.1 200 OK Connection: Keep-Alive Content-Encoding: gzip Content-Length: 67 Content-Location: api.php Content-Type: application/json Date: Wed, 07 Jun 2017 09:23:37 GMT Keep-Alive: timeout=5, max=100 Server: Apache TCN: choice Vary: negotiate,Accept-Encoding { "factors": [ [ "2", 1 ], [ "5", 1 ] ], "id": "10", "status": "FF" }
ãã® factors
ãã©ã表ãã°ããã®ãããããã¤ã¾ãã¾ãããããã§è²ã
調ã¹ã¦ã¿ãã¨æ¬¡ã®ãããªããã°ã«å½ããã¾ããã
æ¸ãã¦ããéãã§ç³ã訳ãªãã®ã§ãããä½ãèããã« interface
ã«æãè¾¼ãã°ããã¿ããã§ãããã¨ã¯åå¦ãã ããã«èªåã§ãããªã«åãå¤ãã¦ããã¾ããä»åã¯2ã¤ã®æ§é ä½ãç¨æãã¾ããã
type FactorDB struct { Status string Id string Factors []Factor } type Factor struct { Number int Power int }
FactorDB
æ§é ä½ã¯è¿ã£ã¦ããã¬ã¹ãã³ã¹ã表ãã¦ãã¾ããStatus
ã Id
㯠string
ã§åé¡ãªãã§ããããFactors
ã ãã¯Arrayã§è¿ã£ã¦ããã®ã§èªåã§ããã«ä¸èº«ãå®ç¾©ãç´ãã¾ãã
å
¬å¼APIããã¥ã¡ã³ããªã©åå¨ããªãã®ã§èªåã§åæã«è§£éãã¦ãã¾ãããfactors
ã¯æååã®æ¹ãæ®ãã®æ°ã§ã¹ãä¹ããã¨ãããããªå½¢ã«ãªã£ã¦ããã¨æ¨å®ãã¾ããw ãªã®ã§ãã®ãããªæ§é ä½ã§æ±ããã¨æãã¾ãã
æçµçã«JSONæååã弿°ã«ã¨ããFactorDB
æ§é ä½ãè¿ãGoã®ããã°ã©ã ã¯æ¬¡ã®ããã«ãªãã¾ããã
func ConvertToFactorDB(b []byte) FactorDB { var base interface{} err := json.Unmarshal(b, &base) if err != nil { log.Fatal("Cannot parse your input") } s := base.(map[string]interface{}) var factor FactorDB factor.Status = s["status"].(string) factor.Id = s["id"].(string) factors := s["factors"].([]interface{}) for _, f := range factors { tmp := f.([]interface{}) number, _ := strconv.Atoi(tmp[0].(string)) power := int(tmp[1].(float64)) factor.Factors = append(factor.Factors, Factor{number, power}) } return factor }
(ãããªæãã§ç°¡åã«æ¸ãã¦ããã¾ããã ãããããã¾ã§ã«3æéãè¦ãã¾ããw)
ã¾ããããããªãã§ãããpackageãåãã¾ãããã¾ã Goã®ããã±ã¼ã¸ã®åãæ¹ããã¾ãè¯ãããã£ã¦ãã¾ããã
How to Write Go Code - The Go Programming Languageã® Your first library ã¨ããé¨åãåèã«åãåãã¾ããã
æ¸ãã¦ããéãã« $GOPATH/src/github/ryosan-470/factordb-go
ã®ãããªå ´æã«ãã¡ã¤ã«ãç½®ããgo build
ã§ä½ãæå¥ãè¨ãããªããã°ã¨ãããã OK ã¨ããã¹ã¿ã³ã¹ã§è¡ãã¾ãw
ãã¹ãã³ã¼ããæ¸ã
æè¿ãã³ã¼ããæ¸ãã¨ãã«ãã¹ãã追å ãã¦ããã¨ããã®ãç§ã®ä¸ã§æµè¡ã£ã¦ããã®ã§ããã¹ããæ¸ãã¾ãããã
åæ§ã«How to Write Go Code - Testingã®ç« ãè¦ã¦ãæ¸ãã¾ããã
Goã«ã¯ assert
ã®ãããªé¢æ°ã¯ãªããæ¯è¼æ¼ç®å ==
ãåºæ¬å以å¤ã§ã¯åä½ããªãããã§ããã®ã§ãèªåã§æ¯è¼ãããããªé¢æ°ãå¥éãã¹ãã«çµã¿å
¥ãã¾ãã
- https://github.com/ryosan-470/factordb-go/blob/af37df2ea6527c3e02aae1140dfaeee69844a28e/handler/response_handler_test.go
- https://github.com/ryosan-470/factordb-go/commit/1fb069da61dba247e61add1673f6d2cbeea481d7
APIã«å®éã«æ¥ç¶
次ã«å®éã«APIã«æ¥ç¶ãããªã¯ã¨ã¹ããéã£ã¦ãå
ç¨âã§ä½ã£ãæ§é ä½ã«ç´ãã¦ããããã°ã©ã ãæ¸ãã¾ãã
ãªããå
ç¨ã® FactorDB
æ§é ä½ã¯æ±ç¨çããããã FactorDbResponse
ã¨ããæ§é ä½ã«ãªã£ã¦ãã¾ãã
https://github.com/ryosan-470/factordb-go/commit/c928408522e91d8dc22888c4f9a5bd82181f37b9
ãã¦ãã¾ãæ§é ä½ã®å®ç¾©ããã¾ããã
type FactorDB struct { Number int Result handler.FactorDbResponse }
ãããããã¨ã§main颿°å
ã§å
ã« var factordb FactorDB
ã¨ãã¦åæåããCLIã§ç¬¬1弿°ã¨ãã¦æ°åãåãåã£ããã¨ã« factordb.Number = 16
ã¿ãããªå½¢ã§ãå¤ãä¿æã§ãã¾ãã
Pythonã§è¨ãã°ãããªæãã§ä½¿ãããã¨ããæ°æã¡ã ãã§ãä¼ãã£ã¦ã»ããã§ãw
class FactorDB(): def __init__(self, n): self.n = n self.result = None
ãã¨ã¯Goããå®éã«æ¥ç¶ãã¦å¤ãåå¾ãã¾ãããã
func (f *FactorDB) Connect() error { values := url.Values{} values.Add("query", fmt.Sprintf("%d", f.Number)) resp, err := http.Get(fmt.Sprintf("%s?%s", ENDPOINT, values.Encode())) if err != nil { return errors.New("cannot connect" + ENDPOINT) } defer resp.Body.Close() b, err := ioutil.ReadAll(resp.Body) if err != nil { return errors.New("empty body") } response := handler.ConvertToFactorDB(b) f.Result = response return nil }
åºã¾ãããããã ãã¤ã³ã¿ã¼ã¬ã·ã¼ãã¼ã§ããw ãããããªãã¸ã§ã¯ãæåããã°ã©ãã³ã°ã§è¨ãã¨ããã®ã¡ã½ããã®ããã«æ±ãã¾ãï¼ ãã¨ã¯main 颿°çã§ä»¥ä¸ã®ãããªæãã§å¼ã³åºãã° OK ã§ãã
if err := factordb.Connect(); err != nil { fmt.Println(err) }
ã¾ããPythonã®ã¡ã½ããã§ããã¨ããã®
- ID ãåå¾ãã:
get_id
- Status :
get_status
get_factor_list
ã«ç¸å½ãããã¤ã³ã¿ã¼ã¬ã·ã¼ãã¼é¢æ°ãå®ç¾©ãã¾ããã¡ãªã¿ã«æå¾ã® get_factor_list
ã¯APIããè¿ã£ã¦ãããµãããå½¢å¼ãããæãã«è¿ãã¦ãããã¡ã½ããã§ä»¥ä¸ã®ãããªã³ã¼ãã§æ¸ããã¦ãã¾ãã
def get_factor_list(self): """ get_factors: [['2', 3], ['3', 2]] Returns: [2, 2, 2, 3, 3] """ factors = self.get_factor_from_api() if not factors: return [] ml = [[int(x)] * y for x, y in factors] return [y for x in ml for y in x]
ãªã¹ãå å 表è¨ãããªããªä½¿ã£ã¦ããã®ã§èªã¿ã¥ããã§ããåãã¨ãã¦ã¯æ¸ãã¦ããã¨ããã§ãã
Goã§ã¯æ¬¡ã®ããã«æ¸ãã¾ããã
func (f *FactorDB) GetFactorList() ([]int, error) { if f.Empty() { return []int{}, errors.New("Empty Result") } var ret []int for _, f := range f.Result.Factors { for i := 0; i < f.Power; i++ { ret = append(ret, f.Number) } } return ret, nil }
ãã¼ããã£ã¡ãæç´w
ãã¹ãã³ã¼ãã¨ãããã®ã¡ã½ããã®Diffå·®åã¯ä»¥ä¸ã§ãã https://github.com/ryosan-470/factordb-go/commit/1657c0397571762061f1c7112c512bd11498c99d
CLIã®å®æ
ãã¦ãããã3ã¤ãçµã¿åããã¦CLIã使ãã¾ããåä½ã¨ãã¦ã¯åç´ã§ç¬¬1弿°ã®å¤ãååããFactorDB
æ§é ä½ã® Number
ã«ä»£å
¥ããFactorDB.Connect
ãå¼ã³ããã¨ã¯ãããªã«å颿°ã§å¤ãæ´å½¢ãã¦æ¨æºåºåã«è¡¨ç¤ºããã¨ãããã®ã§ãã
å¼·ãã¦è¨ãã° JSON å½¢å¼ã§è¿ãã¨ãã«ç©åãç¡çããArrayããJSONæååãæ¸ãåºãã¦ããã¨ãããå°ãæ°æã¡æªãã§ãã
func callAction(c *cli.Context) error { var number = "" if len(c.Args()) > 0 { number = c.Args().First() } n, err := strconv.Atoi(number) if err != nil { log.Fatal("Your input is not number") } f := factordb.FactorDB{Number: n} if err := f.Connect(); err != nil { log.Fatal("Connection Error") } factors, _ := f.GetFactorList() var output string var isJson = c.GlobalBool("json") if isJson { id, _ := f.GetId() status, _ := f.GetStatus() var fs []string for _, f := range factors { fs = append(fs, fmt.Sprintf("%d", f)) } facs := fmt.Sprintf("[%s]", strings.Join(fs, ", ")) output = fmt.Sprintf("{\"id\": \"https://factordb.com/?id=%s\", \"status\": \"%s\", \"factors\": %v}", id, status, facs) } else { output = strings.Trim(fmt.Sprintf("%v", factors), "[]") } fmt.Printf("%s\n", output) return nil }
ã¨ãããããåãã£ã½ãã³ã¼ãã¯ä»¥ä¸ã®ã³ãããããã·ã¥ã§ã§ãã¾ããã
https://github.com/ryosan-470/factordb-go/commit/796c3a6828209561d17bda8813721355b74dfc5e
次㫠Ruby ã§è¨ãã¨ããã® Gemfile çãªãã®ã§å¤é¨ããã±ã¼ã¸ã®ãã¼ã¸ã§ã³ã管çãã¾ããGoã§ã¯glideã¨ãããã®ã使ãã¨ã§ããããã§ãã
https://github.com/ryosan-470/factordb-go/commit/ffeb93d6f289e3a35082c04aaaf574f762a0c1c6
CircleCI 2.0ã使ã£ã¦ãã¹ããã
ãã¦ãããã¾ã§æ¥ããä»åº¦ã¯CIãåãã¾ããããæåãªCIãµã¼ãã¹ã«ã¯TravisãCircleCIãããã¾ããæè¿ã¯CircleCI 2.0ã®é«éãã«é©ãããã¦ãããããCircleCIãæ¡ç¨ãã¾ãããCircleCI 2.0ã¨ã¯ãªãããã¨ãã人ã¯ç§ãéå»ã«æ¸ããè¨äºãèªãã§ã¿ã¦ãã ããã ãã«ãã«VMãå©ç¨ããDockerã³ã³ããããã®ã¾ã¾æ±ããããããã«ãéå§ãé«éã«è¡ããé常ã«ä¾¿å©ã§ãï¼
config.yml ã¯ä»¥ä¸ã®ã¨ããã§ãã
version: 2 jobs: build: docker: - image: circleci/golang:1.8 # CircleCI Go images available at: https://hub.docker.com/r/circleci/golang/ working_directory: /go/src/github.com/ryosan-470/factordb-go steps: - checkout - run: curl https://glide.sh/get | sh - run: make deps - run: make - run: name: Running test code command: make test
ããããªããã«ãã¯ãã¹ã¦ Makefile
ã«æ¸ãã¦ããã¾ãã make test
ã®æåã¨ãã¦ã¯
go test -v $(go list /... | grep -v /vendor/)
ã¨ãªã£ã¦ãã¾ããããã«ãããGlideã§å ¥ã£ã¦ããå¤é¨ã©ã¤ãã©ãªããã¹ãããèªåã®ã³ã¼ãã®ã¿ããã¹ããããã¨ãå¯è½ã«ãªã£ã¦ãã¾ãã
ãã¹ãã«ãã¬ãã¸ã®è¨æ¸¬
ä»åã¯ãã¹ãã«ãã¬ãã¸ã®è¨æ¸¬ã¨ãã¸ã¥ã¢ã«åã®ããã«ãCodecov ã使ãã¾ããã
Goã§coverageãæ¸¬å®ããã«ã¯é£çãããã¿ããã§ãããã調ã¹ã¦ã§ã¦ãããã®ã使ç¨ãã¦ãã¾ãã
https://github.com/ryosan-470/factordb-go/commit/25e3dc1277678e883560191b7944285eab58da67
è¨äºå·çã®æ®µéã§ã«ãã¬ãã¸çã59%ã§Go lintãªã©ã®æ¸¬å®ãã¯ãã£ã¦ããªãã®ã§ããããå ¥ãã¦ãããããªã¨æã£ã¦ããã¨ããã§ãã
Windowsã§åä½ãä¿è¨¼ããããã«Appveyorã使ã
ããã¾ã§æ¥ãããã«ã¯Windowsã§ãã«ããåããã¨ã確ãããããªã¨æãã¾ãããWindowsã§CIãè¡ãããµã¼ãã¹ã®ãã¡æåãªãã®ã«Appveyorãããã¾ããã¯ããã¦ä½¿ã£ã¦ã¿ã¾ãããããã¾ã§é£ãããªãã£ãã®ã§ãã®æ å ±ãå ±æãã¦ããã¾ãã
ç¹ã«ããããªããã°ãWindows Server 2012ä¸ã§ãã¹ããè¡ãããããã§ãã
appveyor.yml
version: 1.0.{build} platform: x64 clone_folder: c:\gopath\src\github.com\ryosan-470\factordb-go environment: GOPATH: c:\gopath install: - set PATH=C:\msys64\mingw64\bin;%PATH% - echo %PATH% - echo %GOPATH% - go version - go env - go get -v -t -d ./... build_script: - go build -o factordb.exe - go test -v -race ./... artifacts: - path: factordb.exe name: binary
ãããªã«é£ãããã¨ã¯ãã¦ããªãã§ããããã ãMakefileã使ããªãã®ã§ãã®é¨åã ãææ¸ãããã¨ããæãã§ãããããä¸å¿ãã¹ããè¡ã£ã¦ããã®ã§ããWindowsã§ã¯ãã«ãã§ããªãã¿ãããªç¶æ³ãèµ·ãã¦ããã¹ãã§è½ã¡ã¦ãããã¨æãã¾ãã
Windowsã®CIã®çµæ:
Pythonçã®CLIã§ãWindowsã§åããã¨ã«ã¯åãã¾ãããWindowsã«ã¯å ã Pythonã¯ãã£ã¦ãã¾ããããæåã³ã¼ãã®åé¡ã§åããªãã£ããã¨ããããããã®ã§ãã¤ããªãåç°å¢ã§åããGoã¯ããã§ããï¼
ããã¾ã§ã§å½¹ã«ç«ã£ãè³æãææ³ãªã©
åºæ¬çã«1次æ å ±ã¯Goã®å ¬å¼ããã¥ã¡ã³ãã§ãããããèªãã°å¤§ä½ã®ãã¨ã¯ãããã¾ãããã ãå¦ä½ããåå¿è ãªã®ã§æå³ãæ±²ã¿åããªããªã©ã®ã¨ãã«é©å½ã«æ¤ç´¢ãã¦ããã¨å¤§æµåããããªãã®ã«ã¶ã¤ãã£ã人ãããã®ã§ããããæ å ±ãå¾ã¾ããã
fmt ã¢ã¸ã¥ã¼ã«ã便å©
fmtã¢ã¸ã¥ã¼ã«ã§ã¯ãå¤ããã åºåããã ãã§ãªããã®å¤ã®åãå¤ã®ä¸èº«ã表示ãããã¨ãã§ãã¾ãã
fmt - The Go Programming Language
ä¸çªä¸ã«æ¸ãã¦ããã¨ããã
%v
: ããã©ã«ããã©ã¼ãããã§å¤ã表示ãããæ§é ä½ã表示ããã¨ãã¯%+v
ã使ã%#v
: å¤ã®Goè¨èªæ§æè¡¨ç¾%T
: å¤ã®åã®Goè¨èªæ§æè¡¨ç¾
ãããã使ã£ã¦ããæãã«ãããã°ãã¦ãã¾ãããåã¨ã©ã¼ã大æµå¤ãæ°ãããã®ã§ããã§printfãããã°ãã¦ç¢ºèªãã¾ãããã
gore ã使ã㨠REPL ãåããã
æ¯åº¦æ¯åº¦ã¡ãã£ã¨ããã³ãã³ãã®ç¢ºèªã«ã³ã³ãã¤ã«ãã¦å®è¡ã¯é¢åãããã®ã§REPLãããã¨ã¯ãã©ãã¾ãã
çå
- Packagingã®åãæ¹ãããããããªã
- Go routineã使ãå ´æããªãã£ãã®ã§ãã®è¾ºãåå¼·ããã
ã¾ã¨ã
Goã¯Pythonããç§»è¡ãã¦ãããã¾ã§é£ãããªãç°¡åã«æ¸ããã¨ãã§ãã¾ãããã¾ããWindowsç¨ã®ãã¤ããªãã¯ãããªã©LinuxãMacã§æ¥ã éçºãã¦ãã人ã«ã¨ã£ã¦ä»ã®ãã£ã¹ããªãã¥ã¼ã·ã§ã³ç¨ã«ãéçºã§ããã®ã¯é常ã«ãããããã§ãã
ãããèå³ãæã£ã¦ããããããã®ãªãã¸ããªã Star ãã¦ãâ¡
ä»åº¦ã¯Slackã®BOTãGoã§æ¸ãç´ãã¦ã¿ããã¨æã£ã¦ãã¾ãã