2.10. 补充注意事项 7-8 结构体自定义类型字段与可变长度字段的初始化与扩容
g g study,d d up!
补充注意事项 7
结构体自定义类型字段
7. 如果结构体中包含自定义类型的字段,需要实现对应的接口方法,例如 Stringer
接口中的 String()
方法,以便在 fmt
包中使用格式化输出时能够正确地显示。
以下是一个使用自定义类型 Person
的示例,其中实现了 Stringer
接口的 String()
方法:
package main
import "fmt"
type Person struct {
Name string
Age int
}
func (p Person) String() string {
return fmt.Sprintf("%s (%d years)", p.Name, p.Age)
}
func main() {
p := Person{"Alice", 30}
fmt.Println(p)
}
在 Person
结构体中定义了 Name
和 Age
两个字段,并实现了 Stringer
接口的 String()
方法,该方法返回一个包含 Name
和 Age
字段值的字符串。在 main()
函数中创建了一个 Person
类型的变量 p
,并通过 fmt.Println()
函数输出该变量,由于 Person
类型实现了 Stringer
接口,因此 fmt
包会调用 String()
方法输出 p
的字符串表示形式。
输出结果为:
Alice (30 years)
由于自定义类型实现了 Stringer
接口的 String()
方法,因此在 fmt
包中可以通过 %v
等格式化标记将其作为字符串输出。
8. 如果结构体中包含可变长度的字段,例如 slice
或 map
,需要特别注意它们的初始化和扩容。
可变长度的字段,例如 slice
或 map
,需要在使用前进行初始化,否则访问它们时可能会出现空指针异常。同时,在添加元素时,需要特别注意是否需要扩容,否则可能会导致数据丢失或程序崩溃。
对于 slice
类型的字段,可以使用 make()
函数进行初始化,并使用 append()
函数添加元素。如果要预先分配足够的空间,可以使用 make()
函数的第二个参数指定 slice
的容量。例如:
type Person struct {
Name string
Age int
Tags []string
}
p := Person{
Name: "Alice",
Age: 30,
Tags: make([]string, 0, 10), // 预先分配 10 个元素的空间
}
p.Tags = append(p.Tags, "tag1", "tag2") // 添加元素
对于 map
类型的字段,可以使用 make()
函数进行初始化,并使用键值对的方式添加元素。例如:
type Person struct {
Name string
Age int
Properties map[string]string
}
p := Person{
Name: "Alice",
Age: 30,
Properties: make(map[string]string),
}
p.Properties["key1"] = "value1" // 添加元素
p.Properties["key2"] = "value2"
需要注意的是,当 slice
或 map
的容量不足时,会发生扩容。扩容会导致重新分配内存,并将原有的元素复制到新的内存空间中。因此,如果 slice
或 map
的元素数量较大,扩容操作会对程序的性能产生影响。因此,在实际编程中需要根据具体情况合理设计 slice
或 map
的容量。
ps:我如果 slice,想要分配不限制个数得空间,如何分配
在 Go 中,可以使用 make
函数来创建 slice,可以通过指定第二个参数为 0 来创建一个没有限制容量的 slice。例如:
s := make([]int, 0, 0)
上面的代码创建了一个空的 slice,并且容量为 0,但是可以随时添加元素而不需要重新分配内存空间。
欢迎关注公众号上海php自学中心,一起交流。