Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
package໊ͱม໊͕ ͔Ϳ͍ͬͯΔͷΛ ͱʹ͔͘ݕग़͍ͨ͠ golang.tokyo #25 2019-06-18 @mackee_w a.k.a macopy 1
Slide 2
Slide 2 text
Ͳ͏͍͏͜ͱ͔ package main import ( "os" "errors" ) func main() { // Ҿ͔Β࣮ߦ͢Δ܅ΛऔΓग़͢ runner := NewRunners(os.Args[1:]) 2
Slide 3
Slide 3 text
errors := make([]error, 0, len(runner)) for _, r := range runners { result, err := runner.Run() if err != nil { errors = append(errors, err) } if result == nil { errors = append( errors, errors.New("result is nil"), ) } 3
Slide 4
Slide 4 text
1ߦา͍ͨΒΕͯΔ errors = append( errors, errors.New("result is nil"), ) • વ͜ΕίϯύΠϧ͕௨Βͳ͍ • errorsύοέʔδطʹ͑ͳ͘ͳ͍ͬͯΔͨΊ 4
Slide 5
Slide 5 text
͜ͷίʔυ͕ੜ·ΕΔࢥߟͷաఔ • errors ͍͍ͨͳΝ(github.com/pkg/errorsͰՄ) • ͦΕ͓͖ͯ͞errorΛ·ͱΊ͓͖͍͔ͯͨΒerrorsͱ͍͏ มΛએݴ͢Δͧ • ΞϨϨɺerrors.Newͱ͔errors.Wrapͱ͔ͷิ͕ޮ͔ͳ ͍ͧ • ͔ͿͬͯΔʂʂʂ 5
Slide 6
Slide 6 text
Έͳ͞ΜͦΜͳܦݧ͋Γ·ͤΜ͔ʁ • ʮ໋໊͕ྑ͘ͳ͍͔ΒͰʁʯ • ͜͜·Ͱ͔͋Β͞·ͳ͜ͱͳͯ͘ɺύοέʔδ໊ͱม໊ ͕͔Ϳͬͯࠞཚ͢Δ͜ͱ͕͋Γ·͢ • ͪͳΈʹࢲ্هͷΑ͏ͳerrorsΛimport͍ͯ͠Δͷʹ errorsΛ࡞Γग़͢͜ͱ͕͋Γ·͢(ຊʹ) • ݪҼ͕ίϯύΠϧΤϥʔͱҧ͏Օॴʹ͋ΔͨΊΘ͔Γʹ͍͘ 6
Slide 7
Slide 7 text
ͦͷଞղܾ͍ͨ͠έʔεstruct໊ͱม໊͕͔ͿΔ type sheet struct { // ... } func NewSheet() *sheet { return &sheet{} } func (s *sheet) String() string { // ... } 7
Slide 8
Slide 8 text
ͦͷଞղܾ͍ͨ͠έʔεstruct໊ͱม໊͕͔ͿΔ ಉ͡ύοέʔδͷҧ͏ϑΝΠϧͰ func DoSomething() { sheet := NewSheet() // ... } 8
Slide 9
Slide 9 text
͜͏ॻ͔ΕΔͱԿ͕ى͜Δ͔ • ίϯύΠϧ௨Δ • DoSomethingͷͰsheetΛࣗͰnewग़དྷͳ͍ 9
Slide 10
Slide 10 text
ύοέʔδͷ໊લͱԾҾ͕͔ͿΔ import "path" func ReadFromFile(path string) error { //... } 10
Slide 11
Slide 11 text
͜͏ॻ͔ΕΔͱԿ͕ى͜Δ͔ • ίϯύΠϧ௨Δ • ReadFromFileͷதͰpathύοέʔδͷ͕ؔݺͳ͘ͳΔ 11
Slide 12
Slide 12 text
ศརͳέʔε͋Δ Ұ෦ͷείʔϓ͚ͩlogΛผͷͷʹஔ͖͑Δͱ͔(ͦͦ͜͜अѱ import "log" // ͜ͷϝιουͷத͚ͩϑΝΠϧʹॻ͘ func Do() { log := log.New(logfile, "Do(): ", log.LstdFlags) // ্ͷ1ߦΛՃ͑Δ͚ͩͰଞͷߦॻ͖͑ͳ͍͍ͯ͘ log.Println("print something") } 12
Slide 13
Slide 13 text
ݴޠ༷͕ѱ͍ͱݴ͍͍ͨΘ͚Ͱͳ͘... ਓؒϛεΛ͢ΔͷͰ... 13
Slide 14
Slide 14 text
ҙਤ͔ͤͣͿͬͯΔ έʔεΛݕ͍ͨ͠ 14
Slide 15
Slide 15 text
github.com/mackee/conflic1dent 15
Slide 16
Slide 16 text
ྫ pathύοέʔδͱmainؔείʔϓͷpathม͕͔ͿͬͯΔ import "path" func main() { path := "example.txt" } 16
Slide 17
Slide 17 text
࣮ߦྫ ίϚϯυ࣮ߦ͢Δͱ $ conflictident . ग़ྗ͜Μͳײ͡ pkgident.go:12:2: conflict identifier name of 'path' by pkgident.go:4:2. 17
Slide 18
Slide 18 text
ରԠ͍ͯ͠Δ͔Ϳ͍ͬͯΔྫ • ύοέʔδ໊ͱม໊ • ύοέʔδ໊ͱԾҾ໊ • ಉ͡ύοέʔδͷܕͱม໊/ԾҾ໊ • ಉ͡ύοέʔδͷconstͷ໊લͱม໊/ԾҾ໊ 18
Slide 19
Slide 19 text
ͱʹ͔͘ศར... 19
Slide 20
Slide 20 text
ྨࣅ • golang.org/x/tools/go/analysis/passes/shadow/ cmd/shadow • มͷshadowingΛݕͯ͘͠ΕΔ func BadRead(f *os.File, buf []byte) error { var err error for { n, err := f.Read(buf) // shadows the function variable 'err' if err != nil { break // causes return of wrong value } foo(buf) } return err } 20
Slide 21
Slide 21 text
ຊݴ͍͍ͨͷ golang.org/x/tools/analysis ͕ศར... 21
Slide 22
Slide 22 text
3ߦͰΘ͔Δx/tools/analysis • ੩తղੳνΣοΧʔΛ࡞ΔϑϨʔϜϫʔΫతͳϥΠϒϥϦ • ੩తղੳʹඞཁͳ ಡΉ, ղੳ͢Δ, ग़ྗ͢Δ ͷ͏ͪ ಡΉ, ग़ྗ͢ Δ ΛΑ͠ͳʹͬͯ͘ΕΔ • ੩తղੳνΣοΧʔͷςετέʔεهड़͕ઈָ 22
Slide 23
Slide 23 text
x/tools/analysisΛ͍ͬͯΔίʔυ package conflictident import ( "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" "golang.org/x/tools/go/ast/inspector" ) var Analyzer = &analysis.Analyzer{ Name: "conflictident", Doc: Doc, Run: run, Requires: []*analysis.Analyzer{ inspect.Analyzer, }, } 23
Slide 24
Slide 24 text
x/tools/analysisΛ͍ͬͯΔίʔυ func run(pass *analysis.Pass) (interface{}, error) { ins := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) nodeFilter := []ast.Node{ // ͜͜ʹཉ͍͠ASTͷϊʔυೖΕΑ͏ } ins.WithStack(nodeFilter, func(n ast.Node, push bool, stack []ast.Node) bool { // ϑΟϧλʹઃఆͨ͠ASTͷϊʔυ͕ͬͯ͘Δͧ ͦΕΛݟ͍͍ͯײ͡ʹग़ྗ͠Α͏ }) } 24
Slide 25
Slide 25 text
x/tools/analysisΛ͍ͬͯΔίʔυ pass.Reportf( ident.Pos(), // ؒҧ͍ͬͯΔίʔυͷϙδγϣϯ "conflict identifier name of '%s' by %s.", name, pos, ) 25
Slide 26
Slide 26 text
x/tools/analysisΛ͍ͬͯΔίʔυ package main import ( "github.com/mackee/conflictident" "golang.org/x/tools/go/analysis/singlechecker" ) func main() { singlechecker.Main(conflictident.Analyzer) } 26
Slide 27
Slide 27 text
conflic&dent͕͍ͬͯΔ͜ͱ • ύοέʔδείʔϓͷܕఆٛΛௐΔ • ϑΝΠϧείʔϓͷimportએݴΛௐΔ • ͦΕͧΕͷؔείʔϓͰએݴ͞ΕͯΔม໊ԾҾ໊͕ ্ه2ͭͱ͔ͿͬͯͨΒग़ྗΛग़͢ 27
Slide 28
Slide 28 text
͜ΕͰ͍͍ײ͡ʹίϚϯυΛ࡞ΕΔʂʂ 28
Slide 29
Slide 29 text
ςετ͕ΊͬͪΌָͳͷΛओு͍ͨ͠ 29
Slide 30
Slide 30 text
͜͏͍͏ίϚϯυͷςετͷ͠͞ • ϑΝΠϧΛ৯ͬͯඪ४ग़ྗʹ݁ՌΛग़͢λΠϓͷίϚϯυ • ࣮ʹΔͱςετ༻ͷϑΝΠϧΛ࡞ͬͯඪ४ग़ྗΛಡΜͰ จࣈྻύʔεͯ͠... • ͪΌΜͱೖྗͱग़ྗΛ͚ͯɺςετͰೖग़ྗΛϞοΫ͢Δ • ↑ x/tools/analysisͰॻ͘ͱࣗવʹ͜Ε͕ग़དྷΔʂʂʂ 30
Slide 31
Slide 31 text
testdataͷ࡞ • testdata/src ҎԼʹ੩తղੳνΣοΧʔͷςετσʔλͷ ίʔυΛॻ͘ • ςετσʔλͷதʹίϝϯτͰظ͢Δग़ྗΛॻ͘ • ςετଆ x/tools/go/analysis/analysistest Λͬ ͯهड़͢Δ 31
Slide 32
Slide 32 text
testdata/src/pkgident/pkgident.go package pkgident import ( "path" ) func hoge() { _ = path.ErrBadPattern } func main() { path, fuga := 1, 1 // want "conflict identifier name of 'path' by testdata/src/pkgident/pkgident.go:4:2." _, _ = path, fuga } func p(path string) { // want "conflict identifier name of 'path' by testdata/src/pkgident/pkgident.go:4:2." } 32
Slide 33
Slide 33 text
conflic&dent_test.go package conflictident_test import ( "testing" "github.com/mackee/conflictident" "golang.org/x/tools/go/analysis/analysistest" ) func Test(t *testing.T) { testdata := analysistest.TestData() analysistest.Run(t, testdata, conflictident.Analyzer, "varspec", "funcarg") } 33
Slide 34
Slide 34 text
ͦͷଞ͓ಘϙΠϯτ • go vetͳͲͰݴ͏ ./... Έ͍ͨͳͷͦͷ··͑Δ • ϞδϡʔϧԽ͍ͯ͠ΔͷͰଞͷLinterͱҰॹʹ࣮ߦ͢ΔίϚϯυ Λ࡞ΕΔ • go modulesରԠࡁΈ 34
Slide 35
Slide 35 text
·ͱΊ • ࢲ͕ϛεΛ͠·͘ΔͷͰɺਖ਼͍͠ίʔυ͕ॻ͚ΔΑ͏ʹ੩తղ ੳνΣοΧʔΛ࡞Γ·ͨ͠ • golang.org/x/tools/analysis Λ͏ͱLinter͕͔ͳΓ؆ ୯ʹॻ͚Δͧʂ • ղੳʹ͕͔͔࣌ؒΔͷͰνϡʔχϯά͍ͨ͠ • ੩తղੳೖʹ࠷దͳͷͰΈΜͳͬͨΒ͍͍ 35
Slide 36
Slide 36 text
Ͱɺ୭ʁ • mackee_w a.k.a @macopy • ໘ന๏ਓΧϠοΫ, 3DϓϦϯλ, ࣗ࡞ ΩʔϘʔυ • ←ࠓि༵ʹחͰΔͷͰདྷͯ͘ Εʂʂʂ 36