Go:在结构体中声明一个切片?

6

我有以下代码:

type room struct {
    width float32
    length float32
}
type house struct{
    s := make([]string, 3)
    name string
    roomSzSlice := make([]room, 3)
} 

func main() {


}

我尝试构建和运行它时,遇到了以下错误:

c:\go\src\test\main.go:10: syntax error: unexpected :=
c:\go\src\test\main.go:11: non-declaration statement outside function body
c:\go\src\test\main.go:12: non-declaration statement outside function body
c:\go\src\test\main.go:13: syntax error: unexpected }

我做错了什么?

谢谢!


只需像其他字段一样声明它即可。在这种情况下,声明为 "s []string";错误信息非常明确地告诉您出了什么问题。 - Snowman
谢谢,但如果我按照你说的方式声明它,那么切片声明和数组声明有什么区别呢? - Gambit2007
一个重要的事情是,数组的类型部分包括它的长度,因此一个有3个元素的数组和一个有4个元素的数组不是同一种类型。如果你声明了一个数组 var n [3]int,那么你就有了一个由3个整数组成的数组,在同样的上下文中使用切片时,你只需要写 var []int,而不需要给出长度。我想说的是,别担心数组;在几乎所有情况下,它们对我们来说都没有直接用处。 - Snowman
make 允许你指定一个切片的长度和容量,但这两个值都是可以改变的。当你使用 make 时,Go 会创建一个无名数组并返回其切片,这也是你唯一直接访问该数组的方式。如果你超出了该数组的限制,则 Go 可以为你创建一个新的、更大的数组,此时你的切片将指向它。 - Snowman
@Snowman,请原谅我,但我不能同意数组在几乎所有情况下都没有直接用处的说法。对于任何基于固定大小的IO,数组是唯一可行的选择。说到固定大小,循环缓冲区也会让我想起来。 - Markus W Mahlberg
@MarkusWMahlberg。很好。我不是说它们没有用处,但我还没有需要过一个。 - Snowman
3个回答

7
您可以在结构体声明中声明一个切片,但是无法初始化它。您需要通过其他方式完成此操作。
// Keep in mind that lowercase identifiers are
// not exported and hence are inaccessible
type House struct {
    s []string
    name string
    rooms []room
}

// So you need accessors or getters as below, for example
func(h *House) Rooms()[]room{
    return h.rooms
}

// Since your fields are inaccessible, 
// you need to create a "constructor"
func NewHouse(name string) *House{
    return &House{
        name: name,
        s: make([]string, 3),
        rooms: make([]room, 3),
    }
}

请将上述内容视为在Go Playground上可运行示例的链接

编辑

根据评论中的要求,为了部分初始化结构体,可以简单地进行更改:

func NewHouse(name string) *House{
    return &House{
        name: name,
    }
}

请将上述内容视为关于Go Playground可运行示例的链接,再次提醒。

谢谢,但如果我不想初始化这个切片(意思是 - 我不想指定其中元素的数量),我该如何做? - Gambit2007
可能最好重新学习一下 tour.golang.org,并且阅读 Effective Go。即使是第二或第三次阅读,也不会有任何坏处。在 make 中简单地删除数字,例如s: make([]string) - Markus W Mahlberg
1
@MarkusWMahlberg 那样行不通 - 切片长度需要作为 make 的参数。@Gambit2007 - 如果你不想初始化它,那就把它的初始值设为零值(完全删除初始化)。它将是 nil,并且长度为 0。如果你想的话,以后可以再初始化它。 - joshlf
@joshlf 我听从了自己的建议。谢谢。 - Markus W Mahlberg
你的意思是这样的:s []string?那不就是数组声明吗? - Gambit2007
@Gambit2007 请查看我的编辑。请注意,SO不是论坛。与其在回答的评论中完善您的问题,不如编辑原始问题以更好地反映您的要求。当然,通知参与者有关更新是有意义的。 - Markus W Mahlberg

7

首先,你不能在结构体内部进行赋值/初始化。 := 运算符既声明又赋值。但是,你可以通过简单的方式达到相同的结果。

这里有一个简单的、微不足道的例子,大致上可以实现你想要的:

type house struct {
    s []string
}

func main() {
    h := house{}
    a := make([]string, 3)
    h.s = a
}

我从未用这种方式编写过,但如果它可以达到你的目的......不管怎样,它都可以编译。

-1

你也可以参考这个:https://golangbyexample.com/struct-slice-field-go/

type student struct {
    name   string 
    rollNo int    
    city   string 
}

type class struct {
    className string
    students  []student
}

goerge := student{"Goerge", 35, "Newyork"}
john := student{"Goerge", 25, "London"}

students := []student{goerge, john}

class := class{"firstA", []student{goerge, john}}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接