我有一个礼节问题。我正在实现一个RPC服务器,这就是为什么此函数采用一个值并在其参数中使用变量的原因。此函数从container/list
读取并填充普通数组缓冲区,以通过变量返回。
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)
,但可以在很大程度上保证所有值都不为空。
我倾向于按原样使用该函数,并使调用者不确定缓冲区的长度(同时仍保证最大可能的缓冲区大小);这主要是因为这是一个相对较高级别的界面,在我继续开发时只会变得更高。有没有我不知道该代码中断的约定?还是某种礼节推动这种方式?
答案 0 :(得分:1)
每个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
}
}