• golang 项目中坑


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

    code snippet

     1 package util
     2 
     3 import (
     4     "math"
     5     "sync"
     6 )
     7 
     8 type IdGenerator interface {
     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(): id overflow")
    29     }
    30 
    31     orig := seed
    32 
    33     //write
    34     seed++
    35     return orig, nil
    36 }

    坑一:struct -> interface

    crawlerutilid.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;    <----  golang 中右边必须是 编译期可以确定的常量。

    而在 cc++ 中,  const b = expr 右边 可以是 运行期才能确定的值。

    如果我要在程序中使用 一个运行期确定的值,同时想限制在后继操作中不能修改此值,在 golang 中如何实现?貌似不能实现。-> 十分苦恼

  • 相关阅读:
    python之递归函数
    python之内置函数
    python之迭代器与生成器
    python之装饰器函数
    python之函数进阶
    python之初识函数
    一起学Android之Dialog
    一起学Android之Menu
    一起学Android之GridView
    一起学Android之ViewPager
  • 原文地址:https://www.cnblogs.com/harrysun/p/4148551.html
Copyright © 2020-2023  润新知