github.com/kaydxh/golang@v0.0.131/tutorial/programming_paradigm/error.handle_test.go (about) 1 package tutorial 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 "io" 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 ) 12 13 // 通过Closure方式抽象相同逻辑代码,去除每次调用都需要if err!=nil判断 14 // 这样内部多一个err 和一个内部函数,感觉不是特别干净 15 func parse(r io.Reader) (*Person, error) { 16 var p Person 17 var err error 18 read := func(data interface{}) { 19 if err != nil { 20 return 21 } 22 err = binary.Read(r, binary.BigEndian, data) 23 } 24 25 read(&p.Name) 26 read(&p.Age) 27 read(&p.Weight) 28 if err != nil { 29 return &p, err 30 } 31 return &p, nil 32 } 33 34 /* 35 this parttern reference go standard library lib 36 scanner := bufio.NewScanner(input) 37 // no error return 38 for scanner.Scan() { 39 token := scanner.Text() 40 // process token 41 } 42 43 // call function finish, use Err() get error 44 if err := scanner.Err(); err != nil { 45 // process the error 46 } 47 */ 48 // 支持流式调用, 调用完成后,检查error 49 // 对于同一个对象调用多个方法,如果有多个对象,就需要每个对象中定义一个error 50 type Person struct { 51 r *bytes.Reader 52 //Buf []byte // read data for name, age and weight 53 Name [10]byte 54 Age uint8 55 Weight uint8 56 err error 57 } 58 59 func (p *Person) read(data interface{}) { 60 if p.err == nil { 61 p.err = binary.Read(p.r, binary.BigEndian, data) 62 } 63 } 64 65 func (p *Person) ReadName() *Person { 66 p.read(&p.Name) 67 return p 68 } 69 70 func (p *Person) ReadAge() *Person { 71 p.read(&p.Age) 72 return p 73 } 74 75 func (p *Person) ReadWeight() *Person { 76 p.read(&p.Weight) 77 return p 78 } 79 80 func (p *Person) Print() *Person { 81 if p.err == nil { 82 fmt.Printf("Name=%s, Age=%d, Weight=%d\n", p.Name, p.Age, p.Weight) 83 } 84 return p 85 } 86 87 func TestError(t *testing.T) { 88 testCases := []struct { 89 b []byte 90 expected string 91 }{ 92 { 93 b: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 94 expected: "", 95 }, 96 } 97 98 for i, testCase := range testCases { 99 _ = testCase 100 t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { 101 r := bytes.NewReader(testCase.b) 102 p := Person{r: r} 103 //can use ppl way to call method, not need to check error 104 p.ReadName().ReadAge().ReadWeight().Print() 105 106 // get error when call pppl over 107 assert.Equal(t, io.EOF, p.err) 108 t.Logf("%+v\n", p) // EOF 109 }) 110 } 111 }