结构体
Go语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型
结构体是由一系列具有相同类型或不同类型的数据构成的数据集合
结构体表示一项记录,类似于其他语言中的class,可以在结构体中定义多个字段,为结构体实现方法、实例化等
定义结构体
结构体定义需要使用 type 和 struct 语句
struct 语句定义一个新的数据类型,结构体中有一个或多个成员
type 语句设定了结构体的名称
定义一个结构体Student,并为Student添加name,age字段
type Student struct {
name string
age int
}
为结构体添加方法
Go不像其他面向对象语言一样,可以写class然后在class里面写方法,但也很巧妙实现了这种效果
我们只需要在普通函数前面加个接收者,这样编译器就知道这个函数属于哪个struct了
语法格式:func (r ReceiverType) funcName(parameters) (results)
示例:为Student实现hello方法
func (stu *Student) hello(person string) string {
return fmt.Sprintf("hello %s, I am %s", person, stu.name)
}
形象一点说,ReceiverType类型的所有字段,方法funcName都是可以使用的,可以认为funcName属于ReceiverType
实现方法与实现函数的区别在于,func和函数名hello之间,加上该方法对于的实例名stu及其类型*Student,可以通过实例名访问该实例的字段name和其他方法了
method特性
- Go中虽没有class,但依旧有method
- 通过显示说明receiver来实现与某个类型的组合
- 只能为同一个包中的类型定义方法
- Receiver可以是类型的值或者指针
- 不存在方法重载
- 可以使用值或指针来调用方法,编译器会自动完成转换
- 从某种意义上来说,方法是函数的语法糖,因为receiver其实就是方法所接收的第一个参数
- 如果外部结构和嵌入结构存在同名方法,则优先调用外部结构的方法
- 类型别名不会拥有底层类型所附带的方法
- 方法可以调用结构中的非公开字段
使用结构体
结构体可以包含多种数据类型,数组只能是单一类型的数据集合
// 创建一个实例
stu := &Student{
name: "Tom",
}
// 调用实例方法
msg := stu.hello("Jack")
fmt.Println(msg) // hello Jack, I am Tom
// 使用New实例化
stu2 := new(Student)
stu2.name = "Cali"
// hello Alice, I am , name 被赋予默认值""
fmt.Println(stu2.hello("Alice"))
struct特性
- Go中的struct与C中的struct非常相似,并且Go没有class
- 使用type <name> struct{}定义结构,名称遵循可见性规则
- 支持指向自身的指针类型成员
- 支持匿名结构,可用作成员或定义成员变量
- 匿名结构也可以用于map的值
- 可以使用字面值对结构进行初始化
- 允许直接通过指针来读写结构成员
- 相同类似的成员可进行直接拷贝赋值
- 支持 == 和 != 比较运算符,但不支持 > 或 <
- 支持匿名字段,本质上是定义了以某个类型名为名称的字段
- 嵌入结构作为匿名字段看起来像继承,但不是继承
- 可以使用匿名字段指针
匿名结构
匿名结构,没有名称的结构体
func main() {
// 匿名结构,没有名称的结构体
a := struct {
Name string
Age int
}{
Name:"Corwien",
Age: 20,
}
fmt.Println(a)
}
匿名结构嵌套
type person struct{
Name string
Age int
Contact struct {
Phone, City string
Code int // 门牌号
}
}
func main() {
a := person{Name:"Corwien", Age:15}
a.Contact.Phone = "10086"
a.Contact.City = "Guangzhou"
a.Contact.Code = 2007
fmt.Println(a)
}
匿名字段
匿名字段:结构体没有命名结构体属性的字段,只有类型
匿名字段必须严格遵守字段类型声明的顺序
type person struct{
string
int
}
func main() {
// 匿名字段必须严格遵守字段类型声明的顺序
a := person{"Corwien", 12}
fmt.Println(a)
}
结构类型比较
type person struct{
Name string
Age int
}
func main() {
// 匿名字段必须严格遵守字段类型声明的顺序
a := person{Name:"Corwien", Age:12}
b := person{Name:"Corwien", Age:12}
fmt.Println(a == b)
}
文章评论