首页 > 解决方案 > 缓冲长度礼仪

问题描述

我有一个礼仪问题。我正在实现一个 RPC 服务器,这就是为什么这个函数需要一个值并在其参数中使用一个外变量。此函数从 a 读取container/list并填充一个普通数组缓冲区,以便通过 out 变量返回。

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
}

[请注意,此函数应限制最大缓冲区大小。]

特别值得注意的是标记线。我正在尝试确定缓冲区是否应始终具有请求的大小(n)并且在实际数据之外为零/零填充,或者缓冲区是否有时应该比请求值短。

如果缓冲区始终是请求的大小,则调用此函数的代码可以使用它作为参数传递的值作为数组循环的一部分。但是,数组中的某些值可能为 nil,因此必须在每个循环中检查 nil:

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

在另一种情况下,调用者无法确定缓冲区大小,len(reply)而是必须调用,但可以在很大程度上保证所有值都不是零。

我倾向于按原样使用该函数,并使调用者不确定缓冲区的长度(同时仍保证最大可能的缓冲区大小);这主要是因为这是一个相对高级别的接口,随着我的继续开发只会变得更高。是否有我不知道此代码中断的约定?还是某种以某种方式推动这种或另一种方式的礼仪?

标签: go

解决方案


每个 Go 程序员都会遇到io.Reader. 这是一个例子,

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
    }
}

可以看到,返回的是实际读取的字节数,所以我们调整缓冲区的大小。然后我们可以使用len(buf)要处理的字节数。


Go 没有类似 C 的空终止字符串。Go 字符串s有一个长度len(s)


并非每种类型都有nil价值。nil仅对指针类型有用。您的示例似乎不起作用。

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
    }
}

推荐阅读