结构体 (struct)
go 中没有对象这一概念, 所以采用了结构体的概念, 结构体在 go 中有着非常重要的位置. 结构体是值类型, 所以可以使用 new 函数来创建. 结构体中字段必须唯一.
结构体定义如下:
- type identifier struct {
- filed type
- filed type
- }
filed 就是结构体的字段名字, type 是字段的类型, 如果暂时不知道命名, 可以使用 _ 来进行占位. 字段可以使用任何类型, 甚至是结构体本身, 也可以是函数或者接口. 一般来说, 给结构体的字段赋值这样即可:
- var s T
- s.a = 1
- s.b = 2
使用 new 函数给一个新的结构体变量分配内存, 返回已分配内存:
- var t *T = new(T)
- // or
- t := new(T)
例子:
- type Person struct {
- Name string
- Age int
- Sex int
- }
- func main() {
- person := new(Person)
- person.Name = "Tim"
- person.Age = 10
- person.Sex = 1
- //or
- person := &Person{"Tim", 10 , 1}
- fmt.Println(person)
- }
- // 输出 &{Tim, 10, 1}
就像面向对象语言那样, 可以使用点来给字段进行赋值, 同样的也可以通过点来进行获取字段的值.
结构体同样可以作为参数进行传递:
- func getPersonName(p *Person) string {
- return p.Name
- }
- func main() {
- ...
- fmt.Prinltn(getPersonName(person))
- }
- // 输出 Tim
如果想知道一个结构体占用了多少内存, 可以使用:
size := unsafe.Sizeof(T{}}
结构体中除了字段和类型外, 还有一个可选的标签, 一个字段的辅助字符串, 只有 reflect 能获取它.
例子:
- type Person struct {
- Name string "Name"
- Age int "Age"
- Sex int "Sex"
- }
- func main() {
- person := Person{}
- person.Name = "Tim"
- person.Age = 10
- person.Sex = 1
- for i := 0; i < 3; i++ {
- refTag(person, i)
- }
- }
- func refTag(p Person, i int) {
- pType := reflect.TypeOf(p)
- iFiled := pType.Filed(i)
- fmt.Println(iFiled.Tag)
- }
- //out
reflect.TypeOf 可以获取变量的正确类型, 如果变量是一个结构体, 就可以通过 Filed 来索引该结构体的字段, 然后就可以使用 Tag 属性.
go 结构体还支持一个特殊字段, 匿名字段. 这些字段没有显式的名字, 只有字段类型, 此时字段类型也就是字段的名字, 匿名字段也可以是一种结构体.
例子:
- type Test1 struct {
- t1 int
- t2 int
- }
- type Test struct {
- a int
- b string
- bool
- Test1
- }
- func main() {
- test := new(Test)
- test.a = 1
- test.b = "2"
- test.bool = true
- test.t1 = 2
- test.t2 = 3
- fmt.Println(test)
- }
- //out &{1, "2", true, 2, 3}
通过 test.bool 的名字来获取匿名字段的数据, 于是可以得出一个结论, 在一个结构体中对于每一种数据类型只能有一个匿名字段. 在结构体内嵌结构体是, 如果遇到命名冲突但是又都需要保留时, 可以使用:
Test.Test1.Filed
这样使用就避免了命名冲突.
方法
go 方法是作用在接收者上的一个函数, 接收者是某种类型的变量, 因此方法是一种类型的函数. 接收者类型几乎可以任何类型, 指针类型和函数类型就不行. 因为方法是函数, 所以方法不能被重载, 对于一个类型只有一个既定名称的方法. 定义方法的格式如下:
- func (r receiver_type) methodName(parmeter_list) (value_list){
- ...
- }
r 是 receiver_type 的实例, methodName 是 r 的方法名, 调用也很简单, r.methodName() 即可. 例子:
- type Person struct {
- Name string
- Age int
- }
- func (p *Person) GetName() string {
- return p.Name
- }
- func (p *Person) GetAge() int {
- return p.Age
- }
- func main() {
- p := new(Person)
- p.Name = "1"
- p.Age = 2
- fmt.Prinltn(p.GetName())
- fmt.Prinltn(p.GetAge())
- }
- // out "1" 2
来源: https://juejin.im/post/5be28fbfe51d4517ad11147e