【问题标题】:Using a string slice that is to be filled at runtime使用要在运行时填充的字符串切片
【发布时间】:2011-01-16 10:41:10
【问题描述】:

我觉得有点傻,因为这应该是一个简单的,但是我刚开始用 go 并无法弄清楚。

package main

import "fmt"

type Question struct {
 q []string
 a []string
}
func (item *Question) Add(q string, a string) {
 n := len(item.q)
 item.q[n] := q
 item.a[n] := a
}

func main() {
 var q Question
 q.Add("A?", "B.")
}

编译时会报错:

q.go:11:12: 错误: 预期 ';'或 '}' 或换行符
q.go:12:12: 错误:预期 ';'或 '}' 或换行符

指 item.q[n] := q 的左大括号和以下行。

我确定我使用了不正确的切片,因为它可以用一个简单的字符串代替,但我不知道如何修复它。

编辑:我已经按照 Pat Notz 的建议使用 StringVectors 重新实现了它,并且效果很好。以下是工作代码:

package main

import (
    fmt "fmt"
    vector "container/vector"
)

type Question struct {
    q vector.StringVector
    a vector.StringVector
}
func (item *Question) Add(q string, a string) {
    item.q.Push(q)
    item.a.Push(a)
}
func (item *Question) Print(index int) {
    if index >= item.q.Len() {
        return
    }
    fmt.Printf("Question: %s\nAnswer: %s\n", item.q.At(index), item.a.At(index))
}
func main() {
    var q Question
    q.Add("A?", "B.")
    q.Print(0)
}

【问题讨论】:

    标签: go containers slice


    【解决方案1】:

    切片只是数组中的一个视图——而不是实际的数组。根据您的代码 sn-p 我认为您想使用 StringVector 包中的 container/vector 。这确实是动态大小数组的唯一选择。内置数组具有固定大小。如果您事先知道要存储多少元素,它们也可以正常工作。

    【讨论】:

      【解决方案2】:

      问题出在 Add 方法中——当你分配一个切片的元素时,你应该使用 '=' 而不是 ':='

      func (item *Question) Add(q string, a string) {
       n := len(item.q)
       item.q[n] = q
       item.a[n] = a
      }
      

      := 运算符仅用于声明新变量

      【讨论】:

      • 虽然使用此方法进行编译,但在运行时会抛出:index out of range panic Aborted
      【解决方案3】:

      您通过将切片委托给 StringVector 来回避使用切片时遇到的问题。我已经修改了您使用字符串切片的初始实现,使其成为有效的工作程序。

      type Question struct {
          q   []string
          a   []string
      }
      

      类型 Question 是一个结构体,它有两个元素 q 和 a,它们是字符串数组的切片。切片隐式包含指向切片开始的数组元素的指针、切片的长度和切片的容量。

      var q Question
      

      声明 q,为 Question 结构分配存储空间,并将结构字段(切片 q.q 和 q.a)初始化为零,即切片指针为 nil,切片 len() 和 cap() 函数返回零。没有为字符串数组分配存储空间;我们需要分开做。

      package main
      
      import "fmt"
      
      type Question struct {
          q   []string
          a   []string
      }
      
      func addString(ss []string, s string) []string {
          if len(ss)+1 > cap(ss) {
              t := make([]string, len(ss), len(ss)+1)
              copy(t, ss)
              ss = t
          }
          ss = ss[0 : len(ss)+1]
          ss[len(ss)-1] = s
          return ss
      }
      
      func (item *Question) Add(q string, a string) {
          item.q = addString(item.q, q)
          item.a = addString(item.a, a)
      }
      
      func main() {
          var q Question
          q.Add("A?", "B.")
          fmt.Println("Q&A", q)
      }
      

      【讨论】:

      • 这个实现比使用 StringVector 差很多,因为这个实现需要所有不必要的分配和复制。看起来 go 库不再有 Vectors。只有列表可用。
      • 你应该使用append 来高效地向切片添加内容
      【解决方案4】:

      你不应该像item.q[n] := q那样使用:=

      := 仅在必须分配给新变量时使用。

      在这种情况下,您只需要使用item.q[n] = q

      使用切片而不是容器/向量也更好。 go(1.0.3) 不再支持向量。

      将项目附加到切片的更好方法是

      slice = append(slice, new_item_1,item_2,item_3)
      

      【讨论】:

        猜你喜欢
        • 2016-01-31
        • 1970-01-01
        • 2020-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-12
        • 2012-10-30
        • 2014-11-18
        相关资源
        最近更新 更多