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  }