Slide 1

Slide 1 text

-F7BO/HIJB!)BOPJ%FW$FOUFS $"HP GoͱาΜͩಓͷΓ͔ΒಘΒΕֶͨͼ

Slide 2

Slide 2 text

GNU1SJOUMO "HFOEB HP1SP fi MF DUY OHIJBMW EFGFS$PODMVTJPO GPSU @5FDIOJRVFT@UP@LFFQ@(P@QSPKFDU@TJNQMF\ UBML@BOE@EFNP U ^ USBDF4UBSU4QBO 5IFNPUJWBUJPOGPSUIJTUBML NZ@FYQFSJFODF@ECMPBE MFTTPOT@MFBSOFE QJDL TJNQMJDJUZ

Slide 3

Slide 3 text

HP1SP fi MF DUY OHIJBMW

Slide 4

Slide 4 text

HP1SP fi MF DUY OHIJBMW { "id": "nghialv", "full_name": "Le Van Nghia", "github_account": "nghialv", "twitter_account": "nghialv2607", "current_team": "Hanoi DevCenter", "current_project": "AI Nasca", "current_possitions": [ "software_engineer", "hr", "father" ], "previous_teams": [ "PipeCD", "Bucketeer", "Kapetanios", "ABEMA", "FRESH!", "Ameba Blog" ] }

Slide 5

Slide 5 text

USBDF4UBSU4QBO 5IFNPUJWBUJPOGPSUIJTUBML NZ@FYQFSJFODF@ECMPBE MFTTPOT@MFBSOFE QJDL TJNQMJDJUZ

Slide 6

Slide 6 text

#FIJOEUIFTFODFT ̍िؒલ ೔ؒલ (P͸γϯϓϧ͗ͯ͢ ൃදωλ͕ͳ͍ (P͔ɺ͏Μ ͠·͢ ΪΞ͞Μɺ$"HP Ͱൃද͠·ͤΜ͔ OHIJBMW GVKJXP ̎ԯ೥લ िؒલ (P͸؆୯͔ͩΒ·ͩ ४උ͠ͳ͍͍ͯ͘ ೔ؒલ (P͸γϯϓϧ͗͢ ೔ؒલ γϯϓϧͩʂ ͜Ε͕ωλͩʂ िؒલ (P͸؆୯͔ͩΒ·ͩ ४උ͠ͳ͍͍ͯ͘

Slide 7

Slide 7 text

The simplicity mindset is the most beautiful thing I learned from Go. It changed the way, I write code, design system, review PRs and even the way I live

Slide 8

Slide 8 text

Simplicity is hard—to design. Simplicity is complicated—to build. But if you get it right... Simplicity is easy—to use. The success of Go proves it. Rob Pike IUUQTHPEFWUBMLTTJNQMJDJUZJTDPNQMJDBUFETMJEF

Slide 9

Slide 9 text

Yes, Go language itself is simple

Slide 10

Slide 10 text

Yes, Go language itself is simple But, our Go project is simple too?

Slide 11

Slide 11 text

GPSU @5FDIOJRVFT@UP@LFFQ@(P@QSPKFDU@TJNQMF\ UBML@BOE@EFNP U ^

Slide 12

Slide 12 text

)PXEPXFTJNQMJGZUIJOH w 4JNQMJDJUZ$PNQMFYJUZ w 5XPBQQSPBDIFTUPTJNQMJGZUIJOH w 3FEVDFFMJNJOBUFJUTDPNQMFYJUZ w )JEFJUTDPNQMFYJUZ w *UJTBDUVBMMZDPNQMFY CVUJUGFFMTTJNQMF

Slide 13

Slide 13 text

)PXEPXFTJNQMJGZUIJOH w 4JNQMJDJUZ$PNQMFYJUZ w 5XPBQQSPBDIFTUPTJNQMJGZUIJOH w 3FEVDFFMJNJOBUFJUTDPNQMFYJUZ w )JEFJUTDPNQMFYJUZ w *UJTBDUVBMMZDPNQMFY CVUJUGFFMTTJNQMF

Slide 14

Slide 14 text

.BOZBTQFDUTUPLFFQTJNQMF w .PEVMF\JOUFSGBDF GVODUJPO TUSVDU QBDLBHF^ w $PODVSSFODZ w &SSPS)BOEMJOH w #PJMFSQMBUF w %FQFOEFODZ w 3FQPTJUPSZ4USVDUVSF w FUD Simplify

Slide 15

Slide 15 text

.BOZBTQFDUTUPLFFQTJNQMF w .PEVMF\JOUFSGBDF GVODUJPO TUSVDU QBDLBHF^ w $PODVSSFODZ w &SSPS)BOEMJOH w #PJMFSQMBUF w %FQFOEFODZ w 3FQPTJUPSZ4USVDUVSF w FUD Simplify -FUTUBMLBCPVUUIJT fi STUUPNBLFJUFBTJFSUP VOEFSTUBOEUIFQSFWJPVTBQQSPBDIFT

Slide 16

Slide 16 text

%FQFOEFODZ3FEVDFEFQFOEFODZDPNQMFYJUZ w 3FEVDJOHSFNPWJOHVOVTFEEFQFOEFODJFT VOVTFEUPPMT w 6TFUIFTUBOEBSEMJCSBSZBTNVDIBTQPTTJCMF w 0OMZCSJOHJOUIJSEQBSUZMJCSBSJFTXIFOBCTPMVUFMZOFDFTTBSZUP BWPJEEFQFOEFODZCMPBU w 6QEBUJOHEFQFOEFODJFTUPUIFMBUFTUWFSTJPOTBMTPNFBOTSFEVDJOH UIFDPNQMFYJUZPGUIFEFQFOEFODZHSBQI HPNJOJNBMJTN

Slide 17

Slide 17 text

%FQFOEFODZ)JEFEFQFOEFODZDPNQMFYJUZ w EBUBCBTFTRMIJEFTUIFDPNQMFYJUZPGFBDIESJWFSJNQMFNFOUBUJPO w *UJTBDUVBMMZDPNQMFY CVU(PVTFSGFFMTTJNQMF w 3FNPUFFOWJSPONFOU FH(JU)VC$PEFTQBDFT JTBHPPEXBZUP IJEFDPNQMFYJUZPGUPPMEFQFOEFODJFT w *UJTBDUVBMMZDPNQMFY CVUUFBNNFNCFSGFFMTTJNQMF 4JNQMJDJUZJTUIFBSUPGIJEJOHDPNQMFYJUZ3PC1JLF

Slide 18

Slide 18 text

'JSTU XFSFEVDFUIFDPNQMFYJUZ *GXFDBOOPUSFEVDFJU XFIJEFJU :FT UIJTJTPVSQBUUFSO

Slide 19

Slide 19 text

*OUFSGBDF)JEJOHDPNQMFYJUZPGJUTDPODSFUF w *OUFSGBDFSFQSFTFOUTUIFDPNQMFYJUZUIBUUIFNPEVMF JNQPTFTUPJUTVTFST w *UIJEFTUIFDPNQMFYJUZPGUIFBDUVBMJNQMFNFOUBUJPOCFIJOE w .PEVMFTIPVMECFEFFQ "1IJMPTPQIZPG4PGUXBSF%FTJHOCPPL

Slide 20

Slide 20 text

*OUFSGBDF,FFQJUTNBMM w 5IFTNBMMFSUIFJOUFSGBDF UIFMFTTDPNQMFYJUZUIBUJUJOUSPEVDFT w .PSFDPODSFUFUZQFTDBOBEBQUUPBTNBMMFSJOUFSGBDF w *OUFSGBDFTBSFDPNQPTBCMF w XFDBODSFBUFDPNQMFYJOUFSGBDFTGSPNTNBMMFSPOFT type Store interface { Get(ctx context.Context, id string) (string, error) BulkUpsert(ctx context.Context, data map[string]string) error Delete(ctx context.Context, id string) error Open() error Close() error } func Show(ctx context.Context, id string, s Store) { data, err := s.Get(ctx, id) } type Getter interface { Get(ctx context.Context, id string) (string, error) } func Show(ctx context.Context, id string, g Getter) { data, err := g.Get(ctx, id) }

Slide 21

Slide 21 text

*OUFSGBDF,FFQJUTNBMM w 5IFTNBMMFSUIFJOUFSGBDF UIFMFTTDPNQMFYJUZUIBUJUJOUSPEVDFT w .PSFDPODSFUFUZQFTDBOBEBQUUPBTNBMMFSJOUFSGBDF w *OUFSGBDFTBSFDPNQPTBCMF w XFDBODSFBUFDPNQMFYJOUFSGBDFTGSPNTNBMMFSPOFT type Store interface { Get(ctx context.Context, id string) (string, error) BulkUpsert(ctx context.Context, data map[string]string) error Delete(ctx context.Context, id string) error Open() error Close() error } func Show(ctx context.Context, id string, s Store) { data, err := s.Get(ctx, id) } type Getter interface { Get(ctx context.Context, id string) (string, error) } func Show(ctx context.Context, id string, g Getter) { data, err := g.Get(ctx, id) } type Reader interface { Read(p []byte) (n int, err error) } type Writer interface { Write(p []byte) (n int, err error) } type Closer interface { Close() error } type ReadWriter interface { Reader Writer } type WriteCloser interface { Writer Closer } type ReadWriteCloser { Reader Writer Closer } .BOZ(PTUBOEBSEQBDLBHFTBMTPXPSLMJLFUIJTFHJPQBDLBHF

Slide 22

Slide 22 text

*OUFSGBDF%F fi OFXIFSFJUJTDPOTVNFE w &OHJOFFSTPGUFOIBWFUIFIBCJUPGEF fi OJOHJOUFSGBDFTPOUIF JNQMFNFOUBUJPOTJEF w 8IZEF fi OJOHXIFSFJUJTVTFE w &MJNJOBUFEFQFOEFODZGSPNDPOTVNFSUPQSPEVDFS w "MMPXDPOTVNFSUPDPOUSPMXIBUJOUFSGBDFJUSFBMMZXBOUT w &BTJFSUPXSJUFUFTUTGPSDPOTVNFS // DO NOT DO IT!!! package producer // producer.go type Thinger interface { Thing() bool } type defaultThinger struct{ … } func (t defaultThinger) Thing() bool { … } func NewThinger() Thinger { return defaultThinger{ … } } package producer // producer.go type Thinger struct{ … } func (t Thinger) Thing() bool { … } func NewThinger() Thinger { return Thinger{ … } } package consumer // consumer.go type Thinger interface { Thing() bool } func Foo(t Thinger) string { … } package consumer // consumer.go import ("producer") func Foo(t producer.Thinger) string { … }

Slide 23

Slide 23 text

'VODUJPO"DDFQUJOUFSGBDF SFUVSODPODSFUF w *ODSFBTFUIF fl FYJCJMJUZPGCPUIJOQVUTBOEPVUQVUT w 'VODUJPODBOBDDFQUBOZUIJOHUIBUGVMM fi MTUIFJOUFSGBDF w 5IFDBMMFSPGGVODUJPODBOIBWFHSFBUFSBDDFTTUPSFUVSOFEWBMVF w %FQFOEFODZ*OWFSTJPO1SJODJQMF %*1 w %FQFOEPOBCTUSBDUJPOT OPUDPODSFUJPOT w 3FEVDFEFQFOEFODZDPNQMFYJUZ w 5IJTJEPNJTVTFEJONBOZQMBDFTJO,VCFSOFUFTDPEFCBTF // Accepting interface func Foo(g getter) // Instead of accepting concrete type func Foo(s *store.Store) // Returning concrete type func NewFoo() (*Thing, error) // Instead of returning interface func NewFoo() (Thinger, error)

Slide 24

Slide 24 text

'VODUJPO0$1XJUIGVODUJPOBMPQUJPOT w 0$10QFO$MPTFE1SJODJQMF w "CMFUPBEEOFXGVODUJPOBMJUZXJUIPVUDIBOHJOHJUTFYJTUJOHDPEF w 'VODUJPOBMPQUJPOTBMMPXFYUFOEJOHDPO fi HVSBUJPOTXJUIPVUDIBOHJOH UIFGVODUJPOTJHOBUVSF w ,FFQUIFGVODUJPOJOUFSGBDFTJNQMF // Option defines a function to set configurable field of Server. type Option func(*Server) // WithPort sets grpc port number. func WithPort(port int) Option { return func(s *Server) { s.port = port } } // WithLogger sets logger to server. func WithLogger(logger log.Logger) Option { return func(s *Server) { s.logger = logger } } func NewServer(service Service, opts ...Option) *Server { }

Slide 25

Slide 25 text

$PODVSSFODZ-FBWFDPODVSSFODZUPUIFDBMMFS w 4ZODISPOPVTDPEFJTTJNQMFS w -FBWFDPODVSSFODZUPUIFDBMMFSTTPUIBUUIFZDBOVTFXIBUFWFS QBUUFSOUIFZMJLFUPBEEDPODVSSFODZ // ListDirectory returns a channel over which // directory entries will be published. When the list // of entries is exhausted, the channel will be closed. func ListDirectory(dir string) chan string // ListDirectory returns the contents of dir. func ListDirectory(dir string) ([]string, error) 'SPNEBWFDIFOFZOFU

Slide 26

Slide 26 text

$PODVSSFODZ-FBWFDPODVSSFODZUPUIFDBMMFS w 4ZODISPOPVTDPEFJTTJNQMFS w -FBWFDPODVSSFODZUPUIFDBMMFSTTPUIBUUIFZDBOVTFXIBUFWFS QBUUFSOUIFZMJLFUPBEEDPODVSSFODZ // ListDirectory returns a channel over which // directory entries will be published. When the list // of entries is exhausted, the channel will be closed. func ListDirectory(dir string) chan string // ListDirectory returns the contents of dir. func ListDirectory(dir string) ([]string, error) 'SPNEBWFDIFOFZOFU func ListDirectory(dir string, fn func(string))

Slide 27

Slide 27 text

$PODVSSFODZ-FBWFDPODVSSFODZUPUIFDBMMFS w 4ZODISPOPVTDPEFJTTJNQMFS w -FBWFDPODVSSFODZUPUIFDBMMFSTTPUIBUUIFZDBOVTFXIBUFWFS QBUUFSOUIFZMJLFUPBEEDPODVSSFODZ // ListDirectory returns a channel over which // directory entries will be published. When the list // of entries is exhausted, the channel will be closed. func ListDirectory(dir string) chan string // ListDirectory returns the contents of dir. func ListDirectory(dir string) ([]string, error) 'SPNEBWFDIFOFZOFU func ListDirectory(dir string, fn func(string)) 5IJTNJHIUCFXIZXFIBWFUIFTBNFJOUFSGBDFGPS UIF8BML%JSGVODUJPOJOUIFTUBOEBSE fi MFQBUIQBDLBHF func WalkDir(root string, fn fs.WalkDirFunc) error

Slide 28

Slide 28 text

&SSPS)BOEMJOH%F fi OFFSSPSTPVUPGFYJTUFODF w &MJNJOBUJOHFSSPSIBOEMJOHCZFMJNJOBUJOHFSSPS w $IBOHFPVSDPEFTPXFEPOPUIBWFFSSPSUPIBOEMF w FH fi MFEFMFUJPOXIFOUIF fi MFJTPQFOJOBQSPDFTT w 8JOEPXT w EPFTOPUQFSNJUCZSFUVSOJOHBOFSSPS w SFRVJSFTVTFSUP fi OEBOELJMMUIFQSPDFTT fi STU w 6OJY w KVTUNBSLTUIF fi MFGPSEFMFUJPOXIFOSFBEZBOESFUVSOTOPFSSPS 3FUVSOJOHFSSPSTJTFBTZIBOEMJOHUIFNJTIBSE

Slide 29

Slide 29 text

&SSPS)BOEMJOH%F fi OFFSSPSTPVUPGFYJTUFODF w (PTUBOEBSEQBDLBHFTBSFBMTPBQQMZJOHUIJTJEFB w FHCV fi PT4DBONFUIPEQFSGPSNTUIFVOEFSMZJOH*0 XIJDIDBOPGDPVSTFMFBEUPBOFSSPS w CVUJUXBTEFTJHOFEUPOPUFYQPTFBOFSSPSBUBMM w JOTUFBE JUSFUVSOTBCPPMFBOBOEBTFQBSBUFNFUIPE func (s *Scanner) Scan() (token []byte, error) scanner := bufio.NewScanner(input) for { token, err := scanner.Scan() if err != nil { return err // or maybe break } // process token } scanner := bufio.NewScanner(input) for scanner.Scan() { token := scanner.Text() // process token } if err := scanner.Err(); err != nil { // process the error }

Slide 30

Slide 30 text

&SSPS)BOEMJOH.BTLJOHFSSPST w &SSPSJTEFUFDUFEBOEIBOEMFEBUBMPXMFWFM TPUIBUIJHIFSMFWFMTOFFEOPUCFBXBSFPGUIFN w 3FUVSOGBTUUPNJOJNJ[FFSSPSIBOEMJOHBUMPXFSMBZFST w FHH31$JOUFSDFQUPSUPWBMJEBUFQBZMPBEPGJODPNJOHSFRVFTUT UIFOUIFSFRVFTUIBOEMFSTBSFGSFFUPIBOEMFUIPTFLJOEPGFSSPST w 0OMZDBSFBCPVUFSSPSTGSPNJUTEJSFDUDIJMET w -PHFSSPSPOMZBUUIFUPQNPTUMBZFS

Slide 31

Slide 31 text

&SSPS)BOEMJOH&SSPSBHHSFHBUJPO w )BOEMFNBOZFSSPSTBUBTJOHMFQJFDFPGDPEF w FHH31$JOUFSDFQUPSIUUQNJEEMFXBSFUPIBOEMFFSSPS w .BOZTUBOEBSEQBDLBHFTBMTPIBOEMFFSSPSCZBEFEJDBUFEUZQF w BSDIJWF[JQ OFUIUUQ CV fi P _, err = fd.Write(p0[a:b]) if err != nil { return err } _, err = fd.Write(p1[c:d]) if err != nil { return err } _, err = fd.Write(p2[e:f]) if err != nil { return err } type errWriter struct { w io.Writer err error } func (ew *errWriter) write(buf []byte) { if ew.err != nil { return } _, ew.err = ew.w.Write(buf) } ew := &errWriter{w: fd} ew.write(p0[a:b]) ew.write(p1[c:d]) ew.write(p2[e:f]) if ew.err != nil { return ew.err }

Slide 32

Slide 32 text

#PJMFSQMBUF$PEFHFOJTZPVSSJHIUIBOE w $PEFHFOFSBUFECZDPEFHFOJTDPOTJTUFOUBOENBJOUBJOBCMF w (FOFSBUFEDPEFTIPVMECFFYQMJDJU w 3FDPNNFOEUPVTF1SPUPDPM#V ff FSTBT%4-BOEUFNQMBUJOH w 8IBUDPEFDBOCFHFOFSBUFE w NPEFM w WBMJEBUJPO w 3#"$ w 42- w DPO fi H w FUD dLMJOFTPGDPEFHFOFSBUFECZ$PEFHFO🎉

Slide 33

Slide 33 text

3FQPTJUPSZ.POPSFQP fi STU w %JWJEFUPDPORVFSCZTQMJUUJOHUIFEJSFDUPSZ w "NPOPSFQPEPFTOPUFRVBUFUPOFFEJOHBMBSHFBOEQPXFSGVM CVJMETZTUFNGPSBMMMBOHVBHFTCFJOHVTFE w 4UBSUXJUIEFGBVMUCVJMETZTUFN w .JOJNJ[FUIFOVNCFSPGFOUSZQPJOUT w .JOJNJ[FUIFOVNCFSPGBSUJGBDUT w ,FFQUIJOHTDPOTJTUFOU

Slide 34

Slide 34 text

EFGFS$PODMVTJPO

Slide 35

Slide 35 text

EFGFS$PODMVTJPO w 5IFTVDDFTTPG(PQSPWFTUIFNFBOJOHPGTJNQMJDJUZ w (PMBOHVBHFJTTJNQMF w 0VS(PQSPKFDUTIPVMEBMTPCFTJNQMF w #VUCFDBSFGVMUPOPUUBLFJUUPPGBS w "OEPVSQBUUFSO 'JSTU XFSFEVDFUIFDPNQMFYJUZ *GXFDBOOPUSFEVDFJU XFIJEFJU

Slide 36

Slide 36 text

HSBDFGVM@TIVUEPXO 5IBOL:PV

Slide 37

Slide 37 text

3FGFSFODFT w #PPLT w "1IJMPTPQIZPG4PGUXBSF%FTJHO w #MPHT w (P$PEF3FWJFX$PNNFOUT(P8JLJ w &SSPSTBSFWBMVFT(P#MPH w 5IF;FOPG(P%BWF$IFOOFZ w 1SBDUJDBM(P3FBMXPSMEBEWJDFGPS XSJUJOHNBJOUBJOBCMF(PQSPHSBNT%BWF$IFOOFZ w 5BMLT w 4JNQMJDJUZJT$PNQMJDBUFE3PC1JLF