005 GO-高级数据类型(结构体和方法)
http://note.youdao.com/noteshare?id=864cc29d2ca6082949d875280f3f5448&sub=D4DF745BF9DE4FADA5A056E2F8DA0B8F
自我理解:
结构体更像类的定义(可以有属性和方法)
一、结构体定义
Go语言的结构体类型(Struct)比函数类型更加灵活。它可以封装属性和操作。前者即是结构体类型中的字段,而后者则是结构体类型所拥有的方法。
二、结构体声明
结构体类型的字面量由关键字type、类型名称、关键字struct,以及由花括号包裹的若干字段声明组成。其中,每个字段声明独占一行并由字段名称(可选)和字段类型组成。示例如下:
type Person struct { Name string Gender string Age uint8 }
三、结构体值类型创建——结构体的值
Person{Name: "Robert", Gender: "Male", Age: 33}
或者
(值的顺序 如果和 值)
Person{"Robert", "Male", 33}
当然,我们在编写某个结构体类型的值字面量时可以只对它的部分字段赋值,甚至不对它的任何字段赋值。这时,未被显式赋值的字段的值则为其类型的零值。注意,在上述两种情况下,字段的名称是不能被省略的。
例如:
// 忽略的字段为 0 或 空 fmt.Println(Books{title: "Go 语言", author: "www.runoob.com"})
四、创建匿名结构体
我们依照结构体类型Person创建一个匿名结构体:
p := struct { Name string Gender string Age uint8 }{"Robert", "Male", 33}
匿名结构体的用途:
匿名结构体最大的用处就是在内部临时创建一个结构以封装数据,而不必正式为其声明相关规则。而在涉及到对外的场景中,我强烈建议使用正式的结构体类型。
五、结构体方法定义
结构体类型可以拥有若干方法(注意,匿名结构体是不可能拥有方法的)。所谓方法,其实就是一种特殊的函数。它可以依附于某个自定义类型。方法的特殊在于它的声明包含了一个接收者声明。这里的接收者指代它所依附的那个类型。我们仍以结构体类型Person为例。下面是依附于它的一个名为Grow的方法的声明:
func (person *Person) Grow() { person.Age++ }
说明: 如上所示,在关键字func和名称Grow之间的那个圆括号及其包含的内容就是接收者声明。其中的内容由两部分组成。第一部分是代表它依附的那个类型的值的标识符。第二部分是它依附的那个类型的名称。后者表明了依附关系,而前者则使得在该方法中的代码可以使用到该类型的值(也称为当前值)
5.1特点:
5.2 机构体方法调用
p := Person{"Robert", "Male", 33} p.Grow()
5.3 注意-接受类型
需要注意的是,在Grow方法的接收者声明中的那个类型是*Person,而不是Person。实际上,前者是后者的指针类型。这也使得person指代的是p的指针,而不是它本身。至于为什么这么做,我们在讲指针的时候在予以揭晓。
5.4 结构体类型没有继承
包含若干字段和方法的结构体类型就相当于一个把属性和操作封装在一起的对象。不过要注意,与对象不同的是,结构体类型(以及任何类型)之间都不可能存在继承关系。
实际上,在Go语言中并没有继承的概念。不过,我们可以通过在结构体类型的声明中添加匿名字段(或称嵌入类型)来模仿继承。具体细节可以参考《Go并发编程实战》中的说明,或者关注我的后续课程。
5.5 结构体类型属于值类型,其零值 不是 nil 而是其中属性的相应类型的零值。
举个例子,结构体类型Person的零值若用字面量来表示的话则为Person{}
六、结构体指针
结构体指针
你可以定义指向结构体的指针类似于其他指针变量,格式如下:
var struct_pointer *Books
以上定义的指针变量可以存储结构体变量的地址。查看结构体变量地址,可以将 & 符号放置于结构体变量前:
struct_pointer = &Book1;
使用结构体指针访问结构体成员,使用 "." 操作符:
struct_pointer.title;
七、练习题
package main
import "fmt"
type Person struct { Name string Gender string Age uint8 Address string } func (p *Person) Move(newAddress string) string { oldAddress := p.Address p.Address = newAddress return oldAddress } func main() { p := Person{"Robert", "Male", 33, "Beijing"} oldAddress := p.Move("San Francisco") fmt.Printf("%s moved from %s to %s.\n", p.Name, oldAddress, p.Address) } |