du1913 2018-07-22 05:27
浏览 3

缓冲长度礼节

I have a question of etiquette. I'm implementing an RPC server, which is why this function takes a value and uses an out-variable in its parameter. This function reads from a container/list and fills a normal array buffer for return through the out-variable.

func (t *PersonalPlaylist) GetPlaylist(n int, reply *[]string) error {
    t.listMutex.Lock()

    bufLen := min(n, t.list.Len()) // mark

    buf := make([]string, bufLen) // mark
    e := t.list.Front()

    for i := 0; i < n; i++ {
        s := e.Value.(string)
        buf[i] = fmt.Sprintf("String #%d: %s", i, s)

        e = e.Next()
        if e == nil {
            break
        }
    }

    *reply = buf

    t.listMutex.Unlock()
    return nil
}

[Note that this function should limit the maximum buffer size.]

Of particular note are the marked lines. I'm trying to decide whether the buffer should always be of the requested size (n) and be zero/nil-filled beyond the real data, or if the buffer should sometimes be shorter than the request value.

If the buffer is always the requested size, the code calling this function can use the value it passed as a parameter as part of the loop through the array. However, some of the values in the array may be nil, so it would have to nil check in each loop:

for i := 0; i < n; i++ {
    if reply[i] == nil {
        break; // or continue
    }
}

In the alternate scenario, the caller can't be sure of the buffer size, and will have to call len(reply) instead, but can be largely guaranteed that all the values will be non-nil.

I'm leaning towards using the function as is, and making callers unsure of the length of the buffer (while still guaranteeing a maximum possible buffer size); this is primarily because this is a relatively high level interface that will only get higher as I continue development. Is there a convention I'm not aware of that this code breaks? Or some etiquette that pushes this one way or another?

  • 写回答

1条回答 默认 最新

  • duanrong0738 2018-07-22 06:28
    关注

    Every Go programmer encounters io.Reader. Here is an example,

    for {
        // io.Reader
        n, err := r.Read(buf[:cap(buf)])
        buf = buf[:n]
        if err != nil {
            // handle error
        }
        // process buf
        for i := 0; i < len(buf); i++ {
            // process byte
        }
    }
    

    As you can see, the number of bytes actually read is returned, so we adjust the size of the buffer. We can then use len(buf) for the number of bytes to process.


    Go does not have C-like null terminated strings. A Go string s has a length len(s).


    Not every type has a nil value. nil is only useful with pointer types. Your example doesn't appear to work.

    var reply *[]string
    for i := 0; i < n; i++ {
        // invalid operation: (*reply)[i] == nil (mismatched types string and nil)
        if (*reply)[i] == nil {
            break // or continue
        }
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度