
çŽæã©ãããããã¯ãšã³ããGoã«ç§»è¡ããã¯ã©ã€ã¢ã³ãã®ããžãã¹ããžãã¯ã®éã3åã®1以äžåæžããæ¹æ³ã«ã€ããŠè©±ããŸããã
察象è
ïŒå°èŠæš¡äŒæ¥ãå²andãã¢ãã€ã«éçºè
ãããã³ãã®ãããã¯ã«èå³ãæã£ãŠããããŸãã¯èå³ãæã£ãŠãããã¹ãŠã®äººã
äœã«ã€ã㊠ïŒGoãžã®ç§»è¡ã®çç±ãééããå°é£ãã¢ãã€ã«ã¢ããªã±ãŒã·ã§ã³ãšãã®ããã¯ãšã³ãã®ã¢ãŒããã¯ãã£ãæ¹åããããã®æé ãšãã³ãã
ã¬ãã« ïŒãžã¥ãã¢ããã³ããã«ã
é·ãéãã¢ãã€ã«éçºã¢ãŠããœãŒã·ã³ã°ã®ããŒã ã¯ãç¬èªã®ããã¯ãšã³ãéçºè
ããããµãŒãããŒãã£ã®ãããžã§ã¯ãã«åãçµã¿ãç¹å®ã®è£œåã®è«è² æ¥è
ãšããŠè¡åããŸããã å¥çŽã«ã¯åžžã«ã¢ãã€ã«éçºè
ãšããŠé³æ¥œãšAPIãå¿
èŠã§ãããšæèšãããŠãããšããäºå®ã«ãããããããããã¯å¿
ãããå©ãã«ã¯ãªããŸããã§ããã

å¿
ãããããã§ã¯ãªãã®ã§ãæè¿ãèªåã®éãå·ã€ãããããªç¶æ³ã®å°ããªã³ã¬ã¯ã·ã§ã³ãäœæããŸããããããéå»ã®èšäºã®1ã€ã§ã¢ããããŒãããŸããã
ãã®ãããããŒã ã«ããªã匷åãªJavaïŒSpringïŒéçºè
ããããããæ°ãã顧客ããšã«ãã£ãããšçºè¡šããããšã«ããŸããã æåã圌ãã¯ãã®ãããªååçãªäœçœ®ãç§ãã¡ã远ãæãããšãæããŠããŸããããããŠãçµå±ç§ãã¡ã¯ãã³ãšæ°Žã§è£žã®ãŸãŸã§ããã§ãããã ãããã倿ããããã«ã亀æžã®æ®µéã§èª°ãããã§ã«ç§ãã¡ãæ°ã«å
¥ã£ãŠããŠã圌ããç§ãã¡ãšååããããªããã»ãšãã©ãã¹ãŠãåæã§ããŸãã ã¯ã©ã€ã¢ã³ããæ¢ã«ããŒã å
ã«èªåã®ã¹ã¿ãããæã£ãŠããå Žåã§ããæåã«äœ¿çšããäºå®ã§ããã æ¬¡ã«ããã€ã¯ããµãŒãã¹ãªã©ã®ã¹ããŒãã¯ãŒããšãã¢ãã€ã«ã¢ããªã±ãŒã·ã§ã³å°çšã®ã¿ã¹ã¯ãå®è¡ããããžãã¹ããžãã¯ãåããå¥ã®ãµãŒããŒãå®è¡ã§ããããšãåŠã³ãŸããã ãã®ã¢ãããŒããåžžã«é©åã§ãããšã¯èšããŸããããããã«ã€ããŠã¯ãã以äžèª¬æããŸããã
è¡ãçç±
ããã€ãã®æåãããããžã§ã¯ãã®åŸãJavaã¯ç§ãã¡ã«ãšã£ãŠéãããŸããã ã¢ããªã±ãŒã·ã§ã³ã«ãšã£ãŠãã¹ãŠãå¯èœãªéã䟿å©ã«ããããã«ãå€ãã®æéãã«ãŒãã³ã«è²»ããããŸããã
äžè¬ã«SpringãšJavaã«ã€ããŠæªãããšãèšããããããŸãããããã¯å·šå€§ãªå€ªãã¹ãã€ã³ã®ã¬ã¬ãªã³è¹ã®ãããªæ·±å»ãªã¿ã¹ã¯ã®ããã®çŽ æŽãããããŒã«ã§ãã ãããŠãç§ãã¡ã¯è»œéã®æµ·è³ã¯ãªãããŒã®ãããªãã®ãæ¢ããŠããŸããã
æ©èœããã°ããå®è£
ããç°¡åã«å€æŽããåç¶æ³ã§æé©ãªãœãªã¥ãŒã·ã§ã³ãæ¢ãããã«é ãæž©ããå¿
èŠã¯ãããŸããã§ããã åé¡ã®å
žåçãªè§£æ±ºçãé·æéã°ãŒã°ã«ã§èª¿ã¹ããšãã«ã©ã®ããã«èµ·ããããç¥ã£ãŠããã®ã§ããããæãé©åã§ããããã®ãã¡10åã®ãã¡5åã¯ãã§ã«å€ããªã£ãŠããŸãã ãããŠã倿°ã®ååã®éžæã«30åããããŸãã
Goã«ã¯ãã®ãããªåé¡ã¯ãããŸããã ãã¹ãŠã®èšèããã æã
ãããªãã¯å®ç§ãªè§£æ±ºçãæ¢ããŠåº§ã£ãŠããŸãããStackOverflowã¯ããã«çããŸããããŸããã¯ããforã«ãŒãã§ãäœãåŸ
ã£ãŠããŸãããïŒã
æéãçµã€ã«ã€ããŠãããªãã¯ããã«æ
£ããŠãããããçš®é¡ã®ããããªããšãç¡æã§ã°ãŒã°ã«ã§æ¢ããŸãããé ããªã³ã«ããŠã³ãŒããæžãã ãã§ãã
é£ããã¯äœã§ãã
ãããããç¶æ¿ã¯ãããŸããã æåã¯è³ãéãã§ããŸããã ããªãã¯OOPã®ããªãã®å
šäœã®èããç Žãã ã¢ãã«ã¿ã€ãã³ã°ã«æ
£ããªããã°ãªããŸããã ç°¡åã«èšãã°ãã¢ãã«ã®ããã«èŠããã¢ãã«ã®ããã«æ³³ããã¢ãã«ã®ããã«é³Žããªããããã¯ã¢ãã«ãããããŸããã
å®éãã€ã³ã¿ãŒãã§ã€ã¹ã®ç¶æ¿ã®ã¿ããããŸãã
ãããŠç¬¬äºã«ãé倧ãªäžå©ãªç¹-å°æ°ã®æ¢è£œããŒã«ããããå€ãã®ãã°ã å€ãã®ããšãéåžžã®æ¹æ³ã§è¡ãããšã¯ã§ããŸããããŸããäžè¬ã«ã¯ã©ã¹ãšããŠäœããæ¬ ããŠããŸãã ããšãã°ãIoCïŒ äŸåé¢ä¿ã®é転 ïŒã®éåžžã®ãã¬ãŒã ã¯ãŒã¯ã¯ãããŸããã çµéšè±ããªããªããºãã¯ãFacebookããã®libããããšèšãã§ãããã ã§ããæçã®ä»æ¹ãããããªãã ããªã®ãããããŸããããããã§ããã®äŸ¿å©ãã¯å®éã«ã¯å€ãã®ããšãæãŸããŠããŸãã åçŽã«Springãšæ¯èŒããããšã¯ã§ããªããããæã§å€ãã®äœæ¥ãè¡ãå¿
èŠããããŸãã
Goå
šäœã®ãã1ã€ã®å°ããªå¶éã¯ãããšãã°ã次ã®åœ¢åŒã®APIãäœæããªãããšã§ãã
/cards/:id /cards/something
æ¢åã®httpã«ãŒã¿ãŒã®å Žåããããã¯çžäºã«æä»çãªèŠæ±ã§ãã ã¯ã€ã«ãã«ãŒã倿°ãšäœãã®ç¹å®ã®ã¢ãã¬ã¹ã®éã§æ··ä¹±ããŸãã æããªå¶éã§ãããããªãã¯ããã«èããªããã°ãªããŸããã 誰ãã解決çãç¥ã£ãŠããã°ãç§ã¯èããŠããããã§ãã
ãŸããå¬ç ãå€ããå°ãªããé©åãªé¡äŒŒäœã¯ãããŸããã ã¯ããå€ãã®ORMããããŸããããããã®ãã¹ãŠã¯ä»ã®ãšããããªã匱ãã§ãã Goã®éçºäžã«èŠãäžã§æé«ã®ãã®ã¯gormã§ãã ãã®äž»ãªå©ç¹ã¯ãããŒã¹ããæ§é ãžã®å¿çã®æã䟿å©ãªãããã³ã°ã§ãã çãããåäœã®ãããã°ã«é·æéãè²»ãããããªãå Žåã¯ããã¢SQLã§ã¯ãšãªãèšè¿°ããå¿
èŠããããŸãã
PS ãã®libã䜿çšããããã»ã¹ã§çºçããåé¿çãåå¥ã«å
±æããããšæããŸãã éåžžã®æ§é ã§ã¯ãªãgormã䜿çšããŠå€æ°ã«æ¿å
¥ããåŸã«idãæžã蟌ãå¿
èŠãããå Žåã¯ãæ¬¡ã®æŸèæã圹ç«ã¡ãŸãã ãªã¯ãšã¹ãã¬ãã«ã§ãid以å€ã«æ»ãçµæã®ååã倿ŽããŸãã
... returning id as value
倿°ãžã®åŸç¶ã®ã¹ãã£ã³ã§ïŒ
... Row().Scan(&variable)
äºå®ã¯ãidãã£ãŒã«ãããªããžã§ã¯ãã®ç¹å®ã®ãã£ãŒã«ããšããŠgormã«ãã£ãŠèªèãããããšã§ãã ãããŠããããè§£ãæŸã€ã«ã¯ããªã¯ãšã¹ãã¬ãã«ã§å¥ã®ååã«å€æŽããå¿
èŠããããŸãã
é·æããŸãã¯ãªãGoã§æžãã®ã
ãšã³ããªãŒã®ãããå€ããå§ããããšæããŸããããã¯æå°éã§ãã åãæ¥ãã©ã®ãããªã¬ã©ã¬ã©ã«ãªã£ãã®ããèŠããŠãããšãGoã¯ãããšæ¯èŒããŠããžã¥ãã¢ã¯ã©ã¹ã§æããããšãã§ããã®ã§ããšãŠãç°¡åã§ãã
ãããŠããã®åçŽãã¯ãèšèªã ãã§ãªãããããæã€ç°å¢ã«ããããŸãã gradleãšmavenã§é·ããããèªãå¿
èŠã¯ãããŸããããã¹ãŠãå°ãªããšã1åã ãéå§ãããããã«é·ãèšå®ãæžãå¿
èŠã¯ãããŸããã ããã§ã¯ãããã€ãã®ããŒã ããã¹ãŠã管çãã䟡å€ã®ããã³ã¬ã¯ã¿ãŒãšãããã¡ã€ã©ãŒã¯ãã§ã«èšèªã®äžéšã§ãããéå§ããããã«è©³çްãªèª¿æ»ãå¿
èŠãšããŸããã
圌ããèšãããã«ïŒç¿åŸãããããç¿åŸãã«ããã ããã¯ç§ãå人çã«åžžã«çŸä»£ã®æè¡ã«æ¬ ããŠãããã®ã§ãã人ã
ã®ããã«äœããããã®ã§ã¯ãªãããã§ãã
ããããéçºã¹ããŒããç¶ããŸãã èšèªã¯1ã€ã®ç®çã®ããã«äœãããŸããïŒ

æ¬è³ªçã«ãããã¯ããžãã¹ã®ããã¯ãšã³ãèšèªã§ãã ããã¯é«éã§ãã·ã³ãã«ã§ãããè€éãªåé¡ãçè§£å¯èœãªæ¹æ³ã§è§£æ±ºããããšãã§ããŸãã è€éãªã¿ã¹ã¯ãšç解床ã«é¢ããŠã¯ãGoã«ã¯goroutinkiããã£ã³ãã«ãªã©ã®ã¯ãŒã«ãªãã®ããããããããã¯è°è«ã®ããã®å¥ã®ãããã¯ã§ãã ããã¯ãèªåã®è¶³ã§æã€æ©äŒãæå°éã®ãæã䟿å©ãªãã«ãã¹ã¬ããã§ãã
建ç¯
Web
Webãã¬ãŒã ã¯ãŒã¯ãšããŠã GinãéžæããŸããã ãŸã RevelããããŸãããç§ãã¡ã«ã¯ããŸãã«ãçãããã®ãã©ãã€ã ãæºãããªãå£è¿°ããŠããããã«èŠããŸããã æè»æ§ãæãããããã«ãããå°ãèªç±ãªæããå§ãããŸãã
Ginã¯ã䟿å©ãªAPIãšäžå¿
èŠãªè€éãã®æ¬ åŠã«é
äºãããŸããã 圌ã®å
¥å ŽéŸå€ã¯éåžžã«äœãã§ãã ãšãŠãå€ãã®ããšã§ãç ä¿®çã¯1æ¥ã§æåéããããçè§£ããŸããã åã«æ··ä¹±ããå Žæã¯ãããŸããã äžç®ã§å¿
èŠãªãã¹ãŠã®æ©èœã
ãã¡ããã圌ã¯åé¡ããªãããã§ã¯ãããŸããã ãã£ãã·ã¥ãªã©ã®ããã€ãã®æ±ºå®ã¯ããµãŒãããŒãã£ã«ãã£ãŠè¡ãããŸãã ãŸããgithubãä»ããã€ã³ããŒãã®äœ¿çšã«æ
£ããŠããå Žåãã€ã³ããŒãã®ç«¶åããããgopkgãä»ããŠã€ã³ããŒããè¡ã£ãå ŽåããŸãã¯ãã®éãåæ§ã§ãã ãã®çµæã2ã€ã®ãã©ã°ã€ã³ã¯åçŽã«çžäºæä»çã«ãªããŸãã
誰ãããã®åé¡ã®è§£æ±ºçãç¥ã£ãŠãããªããã³ã¡ã³ãã«æžããŠãã ããã
äŸåé¢ä¿ãããŒãžã£ãŒ
é·ãéæžããŸããããããã¯ééããªãã°ã©ã€ãã ãšããã«èšããŸãã gradleãŸãã¯mavenã䜿çšããããšãããå Žåã¯ãç¹å®ã®ãã¡ã€ã«å
ã®äŸåé¢ä¿å®£èšã®ãã©ãã€ã ã«ç²ŸéããŠããã®ã§ãå¿
èŠã«å¿ããŠããããåŸã§äœ¿çšã§ããŸãã ãããã£ãŠãGlideã¯ãã ã¹ã¿ãŒGradleã§ãããçŽäºè§£æ±ºããã®ä»ã®å©ç¹ããããŸãã
ã¡ãªã¿ã«ããã¹ãäžã«åé¡ãçºçããå Žåãåãã©ã«ããŒããã¹ãããŠãã³ããŒãã©ã«ããŒã«ãã¹ãã¯ããŒã«ãããšãåé¡ã¯ç°¡åã«è§£æ±ºãããŸãã
go test $(glide novendor)
ãã®ãªãã·ã§ã³ã¯ããã³ããŒãã©ã«ããŒããã¹ãããé€å€ããŸãã glide.yamlããã³glide.lockãã¡ã€ã«ããªããžããªèªäœã«å
¥ããã ãã§ååã§ãã
ããã¯ã¢ãã€ã«éçºã«ã¯äžå圹ç«ã¡ãŸããããç¥ã£ãŠããã ãã§ãïŒ
ORMãšã¬ã«ã
ããã¯ãããã¯ãšã³ãããã¯ã©ã€ã¢ã³ããžã®ããŒã¿ã®è»¢éãšä¿åã«é¢ããèšå€§ãªã»ã¯ã·ã§ã³ã«ãªããŸãã Goããå§ããŠãã¢ãã€ã«ãã©ãããã©ãŒã ã«ã·ãŒã ã¬ã¹ã«ç§»è¡ããŸãã
ãããŠãRealmãšã¯äœã§ããããªãCoreData / Arrays / SQLiteãããåªããŠããã®ã§ããïŒRealmã«ééããããšããªãããããäœã§ããããçè§£ããŠããªãå Žåãã¹ãã€ã©ãŒãæ£ããéããŸããã
ã¬ã«ã ã¯ãã¢ããªã±ãŒã·ã§ã³å
šäœã§ã®ããŒã¿åæã®äœæ¥ã容æã«ããã¢ãã€ã«ããŒã¿ããŒã¹ã§ãã ãªããžã§ã¯ãããŸã ã©ãã«ãä¿åãããŠããªãå Žåã§ããåžžã«ã³ã³ããã¹ãã§äœæ¥ããå¿
èŠãããCoreDataã®ãããªåé¡ã¯ãããŸããã äžè²«æ§ãç¶æããæ¹ãç°¡åã§ãã
ãšã³ãã£ãã£ãäœæããéåžžã®ãªããžã§ã¯ããšããŠæäœãããããŒéã§è»¢éãã奜ããªããã«ãžã£ã°ãªã³ã°ããã ãã§ååã§ãã
圌女ã¯ããªãã®ããã«å€ãã®æäœãè¡ããŸããããã¡ãããããã€ãã®ééãããããŸããäžè¬çã«ã倧æåãšå°æåãåºå¥ããªãæ€çŽ¢ã¯ãããŸããããªã©ã
ãããã®åé¡ã«èãã䟡å€ãããã䟡å€ããããšèããŸããã
èªåèªèº«ãç¹°ãè¿ããªãããã«ã GormãormãšããŠäœ¿çšããããã€ãã®æšå¥šäºé
ã瀺ããŸãã
- æäœæ¥ã§SQLã¯ãšãªãäœæããŸããæ ããªãã§ãã ããã ãŸã SQLãç¿åŸããŠããªãå Žåã
- å¯èœã§ããã°ã1ã€ã®ãã©ã³ã¶ã¯ã·ã§ã³ã§ãªã¯ãšã¹ããäœæããŠãã ããã
- ããŒã¿ããŒã¹ããæäœéå¿
èŠãªãã£ãŒã«ããéžæããŸãã
- ãã¹ãŠãæ§é ã«ãããã³ã°ããŠãã ããã äžé倿°ãå°ãªãã»ã©è¯ãã
ãããããããã¯ãã¹ãŠã®æè¡ã«åœãŠã¯ãŸããŸããããã§ã¯ãç§ã¯å°ãã¹ã«ãã¿ãã«ã§ãããããã§ãã§ãã ç¹°ãè¿ããŸããããªã³ãŒã«ã¯å·ã€ããŸããããéèŠã§ãã
次ã«ãã¢ãã€ã«ã¢ããªã±ãŒã·ã§ã³ã«ã€ããŠèª¬æããŸãã äž»ãªã¿ã¹ã¯ã¯ãã¯ãšãªã§è¿ããããã£ãŒã«ããã¯ã©ã€ã¢ã³ãäžã®å¯Ÿå¿ãããã£ãŒã«ããšåãååã«ãªãããã«ããããšã§ãã ããã¯ãããããã¿ã°ã䜿çšããŠç°¡åã«å®çŸã§ããŸãã

jsonã¿ã°ã®ååãæ£ããããšã確èªããŠãã ããã ãããŠãäŸã®ããã«ã圌ã¯é€å€ãã©ã°ãèšå®ããŠããããšãæãŸããã§ãã ããã«ããã空ã®ãã£ãŒã«ãã§å¿çãä¹±éã«ãªãã®ãé²ããŸãã
ãªãè¡ãã®ïŒæ£ãã質åãããããšãã§ããŸããåãååãä»»æã®èšèªã§äœæã§ããå ŽåãGoã¯ãããšäœãããå¿
èŠããããŸããïŒ ãããŠãããªãã¯æ£ããã§ãããããGoã®å©ç¹ã®1ã€ã¯ããªãã¬ã¯ã·ã§ã³ãšæ§é ã䜿çšããæãç°¡åãªæžåŒèšå®ã§ãã å€ãã®èšèªã«ã¯ãªãã¬ã¯ã·ã§ã³ããããŸãããGoã䜿çšããã®ãæãç°¡åãªæ¹æ³ã§ãã
ãšããã§ãçãããç©ºã®æ§é ãé衚瀺ã«ããå¿
èŠãããå Žåãæè¯ã®æ¹æ³ã¯ãæ§é ã®MarshalJSONã¡ãœããããªãŒããŒããŒãããããšã§ãã
å€ãã¯æ°ã«ãããå€ã®ä»£ããã«æ§é äœã«ãã€ã³ã¿ãŒãããã«æžã蟌ã¿ãŸãããããã¯Goã®æ¹æ³ã§ã¯ãããŸããã Goã¯äžè¬ã«ãå¿
èŠã®ãªããã€ã³ã¿ãŒã奜ãŸãªãã ããã«ãããã³ãŒããæé©åãããã®å¯èœæ§ãæå€§éã«æŽ»çšããããšãã§ããªããªããŸãã
ãã£ãŒã«ãåã«å ããŠããã®ã¿ã€ãã«ã泚æããŠãã ããã æ°åã¯æ°åã§ãªããã°ãªãããè¡ã¯è¡ïŒthanksãcapïŒã§ãªããã°ãªããŸããã æ¥ä»ã«é¢ããŠã¯ãRFC3339ã䜿çšããã®ãæã䟿å©ã§ãã ãµãŒããŒã§ã¯ããªãŒããŒããŒããä»ããŠæ¥ä»ããã©ãŒãããããããšãã§ããŸãã
func (c *Comment) MarshalJSON() ([]byte, error) { type Alias Comment return json.Marshal(&struct { CreatedAt string `json:"createdAt"` *Alias }{ CreatedAt: c.CreatedAt.Format(time.RFC3339), Alias: (*Alias)(c), }) }
ã¯ã©ã€ã¢ã³ãã§ã¯ãããã¯æ¬¡ã®ãã¿ãŒã³ã䜿çšããŠæ¥ä»ããã©ãŒãããããããšã«ããè¡ãããŸãã
"yyyy-MM-dd'T'HH:mm:ssZ"
RFC3339ã®ãã1ã€ã®å©ç¹ã¯ãSwaggerã®ããã©ã«ãã®æ¥ä»åœ¢åŒãšããŠæ©èœããããšã§ãã ãŸãããã®æ¹æ³ã§ãã©ãŒããããããæ¥ä»èªäœã¯ãç¹ã«POSIXæéãšæ¯èŒããå Žåã人éã«ãšã£ãŠéåžžã«èªã¿ããããã®ã§ãã
äžæ¹ãã¯ã©ã€ã¢ã³ãã§ã¯ïŒiOSã®äŸã§ãããAndroidã§ãåæ§ã§ãïŒããã¹ãŠã®ãã£ãŒã«ããšã¯ã©ã¹ã®é¢ä¿ã®ååãå®å
šã«äžèŽããããã1ã€ã®æ±çšã¡ãœããã䜿çšããŠä¿åãå®è¡ã§ããŸãã
func save(dictionary: [String : AnyObject]) -> Promise<Void>{ return Promise {fulfill, reject in let realm = Realm.instance // , . // . try! realm.write { realm.create(T.self, value: dictionary, update: true) } fulfill() } }
é
åã®å Žåãç¶æ³ã¯äŒŒãŠããŸãããä¿åã¯æ¢ã«ã«ãŒãå
ã§å®è¡ãããå¿
èŠããããŸãã å€ãã®å Žåãçµéšã®ãªãéçºè
ã¯ééããç¯ããæžã蟌ã¿ãããã¯å
šäœãã«ãŒãã§ã©ããããŸãã
array.forEach { object in try! realm.write { realm.create(T.self, value: object, update: true) } }
ããã¯ããã¹ãŠãäžæ¬ããŠä¿åããã®ã§ã¯ãªããåãªããžã§ã¯ãã®æ°ãããã©ã³ã¶ã¯ã·ã§ã³ãéãæ¹æ³ã§ãããããæ ¹æ¬çã«ééã£ãŠããŸãã ãŸããæŽæ°ã®éç¥ãæ¥ç¶ããŠããå Žåããã¹ãŠãããã«æ¥œãããªããŸãã ãã©ã³ã¶ã¯ã·ã§ã³ã次ã®ã¬ãã«ã«åŒãäžããŠã次ã®ããã«ããæ¹ãããæ£ç¢ºã§ãã
try! realm.write { array.forEach { object in realm.create(T.self, value: object, update: true) } }
ã芧ã®ãšããããããã³ã°ãæ
åœããäžéå±€ã¯å®å
šã«èœã¡ãŠããŸãã ããŒã¿ãååã«æºåã§ãããã远å ã®åŠçãè¡ããã«ããã«ããŒã¿ããŒã¹ã«åã蟌ãããšãã§ããŸãã ãŸããããã¯ãšã³ããåªããŠããã°ããã»ã©ããã®äœåãªåŠçã¯å°ãªããªããŸãã çæ³çã«ã¯ãæ¥ä»ããªããžã§ã¯ãã«å€æããã ãã§ãã ãã以å€ã¯ãã¹ãŠäºåã«è¡ãå¿
èŠããããŸãã
ã¡ãªã¿ã«ããããã¯ããå°ãé¢ããŠããŸãã ã¯ã©ã€ã¢ã³ãã«æ°žç¶çãªããŒã¿ããŒã¹ãçšæããå¿
èŠããªãå Žåãããã¯ã¬ã«ã ãæŸæ£ããçç±ã«ã¯ãªããŸããã RAMå
ã§å³å¯ã«äœæ¥ãè¡ãããšãã§ããã³ã³ãã³ãããªã³ããã³ãã§ãªã»ããã§ããŸãã
â iOSããã³Androidã®ãªã³ã¯ã
ãã®ã¢ãããŒãã«ãããäžèšã®ãªã¢ã¯ãã£ãããŒã¿ããŒã¹ãšãããã³ã°ã®ãã¹ãŠã®å©ç¹ã掻çšã§ããŸãã
ãŸãã詳现ã«ç¹ã«æ³šæãæã£ãŠãã人ã®ããã«ä»ãå ããããšæããŸããããã§ã¯ãGoãå¯äžã®æ£ãããœãªã¥ãŒã·ã§ã³ã§ãããã¢ãã€ã«éçºã®äžèœè¬ã§ãããšãã声æã¯ãããŸããã 誰ããç¬èªã®æ¹æ³ã§ãã®åé¡ã解決ã§ããŸãã ãã®ãã¹ãéžæããŸããã
Project Goã®æ§é
ããã§ãGoéçºè
åãã®ã³ãŒããå€ããªããŸãã ããªããã¢ãã€ã«éçºè
ã§ããã°ã次ã®ã»ã¯ã·ã§ã³ã«èªç±ã«ã¹ã¯ããŒã«ã§ããŸãã
ããªããå²developeréçºè
ã§ããå Žåãä»ç§ãã¡ã¯æãè峿·±ãããšã«ãªããŸãã å
žåçãªã¢ããªã±ãŒã·ã§ã³ã®ããã¯ãšã³ããäœæããŠãããšä»®å®ããŸããRESTAPIãããã€ãã®ããžãã¹ããžãã¯ãã¢ãã«ãããŒã¿ããŒã¹ããžãã¯ããŠãŒãã£ãªãã£ãç§»è¡ã¹ã¯ãªããããªãœãŒã¹ã®èšå®ãå«ãã¬ã€ã€ãŒããããŸãã ã©ãããããããã¯ã©ã¹ãšããã®ããã«ãããžã§ã¯ãã§ããããã¹ãŠã調æŽãã SOLIDã®ååãå®ããã§ããã°ããã«å€¢äžã«ãªããªãããã«ããå¿
èŠããããŸãã
ãããŸã§ã®ãšãããç§ãã¡ã¯ãããæœè±¡çã«æããŠãããæ·±ãæœã蟌ãã®ã§ã¯ãªããå
šäœçãªæ§é ãçè§£ãããããã«ããŠããŸãã è峿·±ãå Žåã¯ããããæ¬æ Œçãªå¥ã®è³æã«å
ãŠãŸãã ããã§ããGoãšé£æºããã¢ãã€ã«ã¢ããªã±ãŒã·ã§ã³ã«ã€ããŠè©±ããŠãããšããã§ãã
ç§ã®å£°æã§ç¬æçã§ãããµããããªãããã«ããã«äºçŽããŠãã ããã誰ããèªåã®ãããžã§ã¯ãã«åãããã«èªç±ã«ä»äºãããããšãã§ããŸãã
æ§é ã®ã¹ã¯ãªãŒã³ã·ã§ããããå§ããŸãããã

ïŒIntellij Ideaã®ãã ã¹ã¿ãŒã¯ã©ããããããããã§ãããïŒè§Šããã³ã«ïŒ
éå±éãã£ã¬ã¯ããªã«ã¯ãGoãã¡ã€ã«ãŸãã¯ãªãœãŒã¹ãã¡ã€ã«ãäžåºŠã«å«ãŸããŸãã ç°¡åã«èšãã°ããã¹ãŠãéãããŠæå€§éã®æ²¡å
¥æãåŸãããŸãã
ãã®èšäºã§ã¯ãAPIããµãŒãã¹ãããŒã¿ããŒã¹ã®æäœãããã³ããããçžäºã«ã©ã®ããã«äŸåããŠãããã«ã€ããŠãããžãã¹ããžãã¯ã®è²¬ä»»ã«ã€ããŠã®ã¿èª¬æããŸãã 芪æãªãçããããã®ãããã¯ã«èå³ã瀺ãããã1ã€ã®èšäºã«ã¯æ
å ±ãå€ãããã®ã§ãæ®ããæžããŸãã
ã ãããé çªã«ïŒ
Web
ãªã¯ãšã¹ãã®åŠçãæ
åœãããã®ã¯ãã¹ãŠãWebã«ä¿åãããŸãïŒãã€ã³ããŒããã£ã«ã¿ãŒãã³ã³ãããŒã©ãŒ-ãã¹ãŠã®ã¯ãã ä»ãã¯api.goã§è¡ãããŸãã ãã®ãããªçµåã®äŸïŒ
regions := r.Group("/regions") regions.GET("/list", Cache.Gin, rc.List) regions.GET("/list/active", Cache.Gin, regionController.ListActive) regions.GET("", binders.Coordinates, regionController.RegionByCoord)
ã³ã³ãããŒã©ãŒã®åæåãšäŸåé¢ä¿ã®æ³šå
¥ãããã§è¡ãããŸãã å®éã api.goãã¡ã€ã«å
šäœã¯ãã«ãŒã¿ãŒã圢æããã³éå§ãããRunã¡ãœãããšããã¹ãŠã®äŸåé¢ä¿ãšãã®ã°ã«ãŒããæã€ã³ã³ãããŒã©ãŒãäœæããããã®è£å©ã¡ãœããã®ããŒãã§æ§æãããŠããŸãã
Webããã€ã³ããŒ
ãã€ã³ãã¯ãã€ã³ããã©ã«ãã«ãããã¯ãšãªãããã©ã¡ãŒã¿ãè§£æãã䟿å©ãªåœ¢åŒã«å€æããããã«äœæ¥ããããã«ã³ã³ããã¹ãã«ããããããŸãã
ãã®ããã±ãŒãžã®ã¡ãœããã®äŸã ã¯ãšãªãããã©ã¡ãŒã¿ãŒãåãåããboolã«å€æããŠã³ã³ããã¹ãã«å
¥ããŸãã
func OpenNow(c *gin.Context) { openNow, _ := strconv.ParseBool(c.Query(BindingOpenNow)) c.Set(BindingOpenNow, openNow) }
ãšã©ãŒåŠçã®ãªãæãç°¡åãªãªãã·ã§ã³ã ããããããããããã«ã
Web.Controllers
éåžžãã³ã³ãããŒã©ãŒã®ã¬ãã«ã§ã¯ãã»ãšãã©ã®ééããç¯ããŸããäœåãªããžãã¯ãããã·ã¥ããã€ã³ã¿ãŒãã§ã€ã¹ãšåé¢ãå¿ããŠãããäžè¬ã«é¢æ°åããã°ã©ãã³ã°ã«ã¹ã©ã€ãããŸãã äžè¬çã«ãGoã§ã¯ãã³ã³ãããŒã©ãŒã¯iOSãšåãç
æ°ã«èŠããã§ããŸããã³ã³ãããŒã©ãŒã¯åžžã«éè² è·ã«ãªã£ãŠããŸãã ãããã£ãŠãå®è¡ããã¿ã¹ã¯ãããã«æ±ºå®ããŸãã
å
žåçãªã³ã³ãããŒã©ãŒã®äŸãèŠãŠã¿ãŸãããã
ã€ã³ããŒããçç¥ããå Žåãã¯ã©ã¹ã¯ã³ã³ãããŒã©ãŒã€ã³ã¿ãŒãã§ã€ã¹ã§å§ãŸããŸãã ã¯ããã¯ããåžžã«1ã€ã®å®è£
ãããªãå Žåã§ããSOLIDãšããåèªã®æåãDãã確èªããŸãã ããã«ããããã¹ããéåžžã«ç°¡åã«ãªããã³ã³ãããŒã©ãŒèªäœãã¢ãã¯ã«çœ®ãæããããšãã§ããŸãã
type Order interface { PlaceOrder(c *gin.Context) AroundWithPrices(c *gin.Context) }
次ã«ãã³ã³ãããŒã©ãŒæ§é èªäœãšãã®ã³ã³ã¹ãã©ã¯ã¿ãŒããããŸããããã¯ã api.goã§ã³ã³ãããŒã©ãŒãäœæãããšãã«åŒã³åºãäŸåé¢ä¿ãèæ
®ããŸãã
ãããŠæåŸã«ããªã¯ãšã¹ããåŠçããã¡ãœããã ã¬ã€ã€ãŒããã€ã³ããŒã§æ£åžžã«æž¡ããã®ã§ããã¹ãŠã®ãã©ã¡ãŒã¿ãŒãããããšãä¿èšŒããããããã¯æ»æãæããããšãªãMustGetã䜿çšããŠãã©ã¡ãŒã¿ãŒãååŸã§ããŸãã
func (o order)PlaceOrder(c *gin.Context) { m := c.MustGet(BindingOrder).(*model.Order) o.service.PlaceOrder(m) c.IndentedJSON(http.StatusCreated, gin.H { "identifier": m.ID, }) }
ãªãã·ã§ã³ã®ãã©ã¡ãŒã¿ãŒã䜿çšããåãã¹ããŒãªãŒã§ããããã€ã³ããŒã¬ãã«ã§ã®ã¿ããŒãå€ãèšå®ãã䟡å€ããããŸããã³ã³ãããŒã©ãŒã§ãã§ãã¯ã€ã³ããããã©ã«ãå€ã眮ãæããããåã«ç¡èŠããŸãã
ãµãŒãã¹
ãµãŒãã¹ã®ç¶æ³ã¯ã»ãšãã©åãã§ãããŸãããµãŒãã¹ã¯ã€ã³ã¿ãŒãã§ãŒã¹ãæ§é ãã³ã³ã¹ãã©ã¯ã¿ãŒã§å§ãŸãããã®åŸã«äžé£ã®ã¡ãœãããç¶ããŸãã 1ã€ã®è©³çްã«çŠç¹ãåœãŠãããšæããŸã-ãããããŒã¿ããŒã¹ãæäœããååã§ãã
ãµãŒãã¹ã®ã³ã³ã¹ãã©ã¯ã¿ã¯ããããåäœããäžé£ã®ãªããžããªãšãã©ã³ã¶ã¯ã·ã§ã³ãã¡ã¯ããªãèæ
®ããå¿
èŠããããŸãã
func NewOrder(repo repositories.Order, txFactory TransactionFactory) Order { return &order { repo: repo, txFactory: txFactory } }
ãã©ã³ã¶ã¯ã·ã§ã³ãã¡ã¯ããªã¯ãã©ã³ã¶ã¯ã·ã§ã³ãçæããåãªãã¯ã©ã¹ã§ãããè€éãªãã®ã¯ãããŸããã
type TransactionFactory interface { BeginNewTransaction() Transaction }
gormã®å®å
šãªå·¥å Žã³ãŒã type TransactionFactory interface { BeginNewTransaction() Transaction } type transactionFactory struct { db *gorm.DB } func NewTransactionFactory(db *gorm.DB) TransactionFactory { return &transactionFactory{db: db} } func (t transactionFactory)BeginNewTransaction() Transaction { tx := new(transaction) tx.db = t.db tx.Begin() return tx }
ãããããã©ã³ã¶ã¯ã·ã§ã³èªäœã§åæ¢ãã䟡å€ããããŸãã ãããããããã¯äœã«ã€ããŠã§ããã ãã©ã³ã¶ã¯ã·ã§ã³ã¯å®è£
ãšåãã€ã³ã¿ãŒãã§ãŒã¹ã§ããããã©ã³ã¶ã¯ã·ã§ã³ã®éå§ãå®äºãããŒã«ããã¯ãããã³ä»¥äžã®ãšã³ãžã³ã¬ãã«ã®å®è£
ãžã®ã¢ã¯ã»ã¹ã®ããã®ã¡ãœãããå«ãŸããŠããŸãã
type Transaction interface { Begin() Commit() Rollback() DataSource() interface{} }
gormã®å®å
šãªãã©ã³ã¶ã¯ã·ã§ã³ã³ãŒã type Transaction interface { Begin() Commit() Rollback() DataSource() interface{} } type transaction struct { Transaction db *gorm.DB tx *gorm.DB } func (t *transaction)Begin() { t.tx = t.db.Begin() } func (t *transaction)Commit() { t.tx.Commit() } func (t *transaction)Rollback() { t.tx.Rollback() } func (t *transaction)DataSource() interface{} { return t.tx }
begin ã commit ã rollbackã§ãã¹ãŠãã¯ãªã¢ããå¿
èŠãããå ŽåãDatasourceã¯äœã¬ãã«ã®å®è£
ã«ã¢ã¯ã»ã¹ããããã®åãªãæŸèæã§ããGoã®ããŒã¿ããŒã¹ã§ã®äœæ¥ã¯ããã©ã³ã¶ã¯ã·ã§ã³ã倿Žãããèšå®ãæã€ããŒã¿ããŒã¹ãžã®ã¢ã¯ã»ãµãŒã®åãªãã³ããŒã«ãªãããã«èšèšãããŠããããã§ã åŸã§ãªããžããªã§äœæ¥ãããšãã«å¿
èŠã«ãªããŸãã
å®éãããã¯ãµãŒãã¹ã¡ãœããã§ãã©ã³ã¶ã¯ã·ã§ã³ãæäœããäŸã§ãã
func (o order)PlaceOrder(m *model.Order) { tx := o.txFactory.BeginNewTransaction() defer tx.Commit() o.repo.Insert(tx, m) }
ãã©ã³ã¶ã¯ã·ã§ã³ãéå§ããããŒã¿ããŒã¹ã«ã¢ã¯ã»ã¹ããå¿
èŠã«å¿ããŠã³ããããŸãã¯ããŒã«ããã¯ããŸããã
ãã¡ããããã©ã³ã¶ã¯ã·ã§ã³ã®å©ç¹ã¯ããã€ãã®æäœã§ç¹ã«æããã«ãªããŸãããäŸã®ããã«1ã€ãããªããŠããããã¯ããã»ã©æªãã¯ãªããŸããã
å°éå®¶ã«åé¢ã¬ãã«ãå¶åŸ¡ã§ããªãããšãç¥ã£ãŠããŸãã
ãŸã æµ
ç¬ãèŠã€ããã-ã³ã¡ã³ãã«æžããŠãã ããã
åŸèŒ©ãžã®è¿œå ã®ã¢ããã€ã¹ãšããŠãã§ããã ãæ©ãååŒãéå§ãã¹ãã ãšèšãããã§ãã ãã¹ãŠã®ããŒã¿ãæºåããŠãéå§ãšã³ãããã®éã«æå°éã®ããžãã¯ãšèšç®ãã§ããããã«ããŸãã
ãã©ã³ã¶ã¯ã·ã§ã³ãéããã人ã
ãå«ç
ããŠãããšãã°Googleã«ãªã¯ãšã¹ããéä¿¡ããããšãèµ·ãããŸãã ãããŠã圌ãã¯ãªãããããã¹ãŠãããããã¯ã§èµ·ãã£ãã®ã ãããšæããŸãã
è峿·±ãäºå®
çŸä»£ã®å€ãã®ããŒã¿ããŒã¹ã§ã¯ã ãããããã¯ã¯ã§ããã ãåçŽã«ãã¿ã€ã ã¢ãŠãã«ãã£ãŠå®çŸ©ãããŠããŸãã è² è·ã倧ããå Žåããããã¯ã®ããã®ãªãœãŒã¹ã®ã¹ãã£ã³ã¯é«äŸ¡ã§ãã ãããã£ãŠã代ããã«éåžžã®ã¿ã€ã ã¢ãŠãããã䜿çšãããŸãã ããšãã°ã mysqlã§ ã ãã®æ©èœãããããªãå Žåã¯ãæãçŽ æŽãããæéã®æ¥œãããããã°ãèªåã§è¡ãããšãã§ããŸãã
ãªããžããª
åãããšïŒã€ã³ã¿ãŒãã§ãŒã¹ãæ§é ãã³ã³ã¹ãã©ã¯ã¿ãŒã¯ãååãšããŠæ¢ã«ãã©ã¡ãŒã¿ãŒãªãã§ãã
ãµãŒãã¹ã³ãŒãã§åŒã³åºããæ¿å
¥æäœã®äŸã瀺ããŸãã
func (order)Insert(tx Transaction, m *model.Order) { db := tx.DataSource().(*gorm.DB) query := "insert into orders (shop_id) values (?) returning id" db.Raw(query, m.Shop.ID).Scan(m) }
ãã©ã³ã¶ã¯ã·ã§ã³ããäœã¬ãã«ã®ã¢ã¯ã»ã¹ä¿®é£Ÿåãåãåãããªã¯ãšã¹ããã³ã³ãã€ã«ããŠå®äºããŸããã ã§ãã
ããã¯ãã¹ãŠãã¢ãŒããã¯ãã£ãå°ç¡ãã«ããªãããã«ååãªã¯ãã§ãã å°ãªããšãéãããã ã質åãç°è°ãããå Žåã¯ãã³ã¡ã³ããæžããŠãã ãããç§ã¯è°è«ããŠåãã§ããã§ãããã
ã¢ããª
ããŠããŽãŒãã¡ãŒã¯ããã§ãããä»ã©ã®ããã«ã¯ã©ã€ã¢ã³ããšä»äºãããŠããŸããïŒ
Goã®å Žåãšåæ§ã«ãã¹ã¿ãã¯ããå§ããŸãããã äžè¬çã«ãç§ãã¡ã¯ã»ãŒãã¹ãŠã®å Žæã§è©Šè¬ãç©æ¥µçã«äœ¿çšããŠããŸãããããã§ã¯ãããã«èª°ãã®ç²Ÿç¥ãå·ã€ããªãããã«ãããç©ãããªããŒãžã§ã³ã®ã¢ãŒããã¯ãã£ã«ã€ããŠèª¬æããŸãã
ã¹ã¿ãã¯
ãããã¯ãŒã¯å±€ ïŒ
Swiftãããžã§ã¯ãã®Alamofireããã³Objective-Cã®AFNetworking ã
ãšããã§ãAlamofireãAFNetworkingã§ããããšãç¥ã£ãŠããŸãããïŒ AFNetworkingã©ã€ã»ã³ã¹ãèŠãã°ãããããã«ã AFãã¬ãã£ãã¯ã¹ã¯Alamofireãæå³ããŸãã

ç絡 ïŒ
callback- / . , . , .
. iOS: PromiseKit . â , , , success/failure , always, , / . , .
, â . flow , . , , , :
func details(id: Int) -> Promise<Void> { return getDetails(id) .then(execute: parse) .then(execute: save) }
getDetails, :
func getDetails(id: Int) -> Promise<DataResponse<Any>> { return Promise { fulfill, reject in Alamofire.request(NetworkRouter.drugDetails(id: id)).responseJSON { fulfill($0) } } }
, . , . , . , .
func parseAsDictionary(response: DataResponse<Any>) -> Promise<[String:AnyObject]> { return Promise {fulfill, reject in switch response.result { case .success(let value): let json = value as! [String : AnyObject] guard response.response!.statusCode < 400 else { let error = Error(dictionary: json) reject(error) return } fulfill(json) break case .failure(let nserror): let error = Error(error: nserror as NSError) reject(error) break } } } // , func save(items: [[String : AnyObject]]) -> Promise<Int> { return Promise {fulfill, reject in let realm = Realm.instance try! realm.write { items.forEach { item in // generic realm.create(Item.self, value: item, update: true) } } fulfill(items.count) } }
, MVC, :
_ = service.details().then {[weak self] array -> Void in
ããŒã¿ããŒã¹
, ORM Go-side, , . - , . , datasource . , .
fine-grained notifications , .
extra- class ViewController: UITableViewController { var notificationToken: NotificationToken? = nil override func viewDidLoad() { super.viewDidLoad() let realm = try! Realm() let results = realm.objects(Person.self).filter("age > 5") // Observe Results Notifications notificationToken = results.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in guard let tableView = self?.tableView else { return } switch changes { case .initial: // Results are now populated and can be accessed without blocking the UI tableView.reloadData() break case .update(_, let deletions, let insertions, let modifications): // Query results have changed, so apply them to the UITableView tableView.beginUpdates() tableView.insertRows(at: insertions.map({ IndexPath(row: $0, section: 0) }), with: .automatic) tableView.deleteRows(at: deletions.map({ IndexPath(row: $0, section: 0)}), with: .automatic) tableView.reloadRows(at: modifications.map({ IndexPath(row: $0, section: 0) }), with: .automatic) tableView.endUpdates() break case .error(let error): // An error occurred while opening the Realm file on the background worker thread fatalError("\(error)") break } } } deinit { notificationToken?.stop() } }
, ApiManager.swift . , , â extension ApiManager, .
singleton, . , , .
SOA (service oriented architecture). Rambler , , , .
. â . , . , viewDidLoad. , , . , , , , , .
:

, . , 200-300 . , , .
, : , . , .
ãããã«
ãŸãšãããšã Realm- mobile-side , . , -, . , iOS Android, â !
, . , , - .
. .
, . , , , , , , ? MVP MVVM , .
, , : â, ?â : â, .â
.
, , . , , .
PS . ? , , . , , , , .