tags:

views:

74

answers:

3

I feel a little silly as this should be an easy one, however I just started with go and can't figure it out.

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.")
}

When Compiling it gives the errors:

q.go:11:12: error: expected ';' or '}' or newline
q.go:12:12: error: expected ';' or '}' or newline

that refers to the opening brace of item.q[n] := q and the following line.

I'm certain that I'm using slices incorrectly as it works fine with a simple string instead, but I'm not sure how to fix it.

edit: I have re-implemented it using StringVectors as per Pat Notz's advice and it works well. The following is the working code:

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)
}
+1  A: 

A slice is simply a view into an array -- not an actual array. Based on your code snippet I think you want to use StringVector from the container/vector package. That's really your only choice for dynamically sized arrays. The built in arrays have a fixed size. They'd work fine too if you know in advance how many elements you want to store.

Pat Notz
thanks, I'll look into that!
roamn
A: 

The problem is in the Add method -- when you assign an element of a slice, you should use '=' instead of ':='

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

The := operator is only used for declaring new variables

marketer
while it does compile using this method, at runtime it throws:index out of rangepanicAborted
roamn
+1  A: 

You sidestepped the problems you were having using slices by delegating them to StringVector. I've revised your initial implementation, which used string slices, to become a valid, working program.

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

The type Question is a struct which has two elements, q and a, which are slices of an array of strings. A slice implicitly contains a pointer to the element of the array which begins the slice, the length of the slice, and the capacity of the slice.

var q Question

declares q, allocating storage for the Question struct, and initializes the struct fields (slices q.q and q.a) to zero i.e. the slice pointers are nil, and the slice len() and cap() functions return zero. No storage is allocated for string arrays; we need to do that separately.

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