LXY3800 发表于 2018-9-20 06:10:23

golang 项目中坑

  今天试着按照上一篇博客的设计自己实现自己的crawler,踩了一路坑。有些找到了答案,有些没有。我先将这些坑记录下来,然后divide and conquer。
  code snippet
  

1 package util  

2  
3 import (
  
4   "math"
  
5   "sync"
  
6 )
  
7

  
8 type>  
9   NextId() (uint64, error)
  
10 }
  
11
  
12 type myIdGenerator struct {
  
13   rwmutex sync.RWMutex
  
14   seed    uint64
  
15 }
  
16
  
17 func NewIdGenerator() (*IdGenerator, error) {
  
18   return new(myIdGenerator), nil
  
19 }
  
20
  
21 //???RWMutex - two steps:write after read.
  
22 func (this *myIdGenerator) NextId() (uint64, error) {
  
23   this.rwmutex.Lock()
  
24   defer this.rwmutex.Unlock()
  
25
  
26   //read
  
27   if this.seed == math.MaxUint64 {

  
28         return 0, error.New("util.id.NextId():>  
29   }
  
30
  
31   orig := seed
  
32
  
33   //write
  
34   seed++
  
35   return orig, nil
  
36 }
  

  坑一:struct -> interface
  crawler\util\id.go:18: cannot use new(myIdGenerator) (type *myIdGenerator) as type *IdGenerator in return argument:
  *IdGenerator is pointer to interface, not interface
  solution: http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go
  坑二:RWMutex read lock and write lock
  本来计划,用读锁保护 seed 的读取,之后用写锁保护seed 的修改。但是这个读取和写应该在一个transaction中,也就是说在自己读取到seed 和写seed之间,seed 不能被其他实体修改。
  如果在读锁Lock时候,写锁重入(假定支持锁升级重入),那么就会出现一种经典的死锁现象。A, B 都申请到了读锁,现在A准备升级到写锁,A等待B释放读锁,B也要升级而等待A释放读锁。
  本例中,资源锁定的范围并不大,一致用写锁对性能影响并不十分严重。但是如果读写临界区都比较大,那么怎么解决呢?
  坑三:interface 到底是 struct 还是 pointer? 这个应该与第一个坑属于同一个问题的不同表象。
  

1 package base  
2
  
3 import (
  
4   "net/http"
  
5 )
  
6
  
7 type Response struct {
  
8   resp*http.Response
  
9   depth uint
  
10 }
  
11
  
12 ...
  
13
  
14 func (this *Response) Valid() bool {
  
15   if this.resp != nil && this.resp.Body != nil {
  
16         return true
  
17   }
  
18
  
19   return false
  
20 }
  

  注意这行代码,
  

this.resp != nil && this.resp.Body  

  从定义中我们知道this.resp的类型是一个指针,所以其零值是一个指针。但是我们怎么知道 this.resp.Body表示什么,它是一个接口,其定义如下:
  

1 // Body represents the response body.  

2   //  
3   // The http Client and Transport guarantee that Body is always
  
4   // non-nil, even on responses without a body or responses with
  
5   // a zero-lengthed body.
  
6   //
  
7   // The Body is automatically dechunked if the server replied
  
8   // with a "chunked" Transfer-Encoding.
  
9   Body io.ReadCloser
  

  是不是接口的实际类型都是指针,其零值都是nil?
  如果接口可以表示struct, 那么编译器如何判断 obj == nil 类型是否匹配?难道编译器知道interface 对应的真实类型, 用它的真实类型来判断的吗?
  坑四   const in golang
  golang 中的 const 比 c/c++中的 const 限定更加严格。
  golang:   const a =expr;   十分苦恼


页: [1]
查看完整版本: golang 项目中坑