19.面对对象1之struct结构体
Go中面向对象是通过struct来实现,struct是用户自定义的类型,首先需要定义struct
1: type User struct {2: Username string
3: Sex string
4: Age int5: AvatarUrl string
6: }
初始化方法1
1: var user User
2: user.Age = 18
3: user.Username = "user01"4: user.Sex = "男"5: user.AvatarUrl = "http://my.com/xxx.jpg"
初始化方法2
//也可以部分初始化,这样没有初始化的部分具体值就是对应数据的默认值
1: var user User = User {
2: "Username" : "user01",3: // "Age" : 18,
4: "Sex" : "男",5: "AvatarUrl" : "http://my.com/xxx.jpg",6: }
更简单的写法
1: user := User {
2: "Username": "user01",3: "Age": 18,
4: "Sex":"男",5: "AvatarUrl":"http://my.com/xxx.jpg",6: }
结构体类型的指针
// &User{}和new(User)本质上是一样的,都是返回一个结构体的地址
1: var user01 *User = &User {}
2: fmt.Pringln(user01)
1: >>> &{ 0 }
// 序列化的时候传入指针类型,节省内存,如果不传,就是复制了一个新的User。
1: var user01 *User = &User {
2: user01.Age = 18
3: //等同于(*user01).Age = 18
4: user01.Username = "user01"5: fmt.Printf("user01:%#v\n", user01)6: }
1: >>> user01:&main.User{Username:"user01", Sex:"", Age:18, AvatarUrl:""}
struct内存布局
结构体的内存布局:占用一段连续的内存空间,每一块内存指向数据对应的地址
1: type Test struct {2: A int323: B int324: C int325: D int326: }7: func main() {8: var t Test9: fmt.Printf("a addr:%p\n", &t.A)
10: fmt.Printf("a addr:%p\n", &t.B)
11: fmt.Printf("a addr:%p\n", &t.C)
12: fmt.Printf("a addr:%p\n", &t.D)
13: }14: >>> a addr:0xc00000c0b015: a addr:0xc00000c0b416: a addr:0xc00000c0b817: a addr:0xc00000c0bc
结构体没有专门的构造函数,必要的话要自己写
1: type User struct {2: Username string
3: Sex string
4: Age string
5: AvatarUrl string
6: }7:8: func NewUser(username string,sex string,age int, avatar string) *User {9: // 第一种写法
10: //user := &User {
11: //Username : username,
12: //Sex : sex,
13: //Age : age,
14: //AvatarUrl : avatar,
15: //}
16: //第二种写法
17: user := new(User)18: user.Username = username
19: user.Sex = sex
20: user.Age = age
21: user.AvatarUrl = avatar
22: return user23: }24:25: func main() {26: u := NewUser("user01", "女", 18, "xxx.jpg")27: fmt.Printf("user=%#v\n", u)
28: }
1: >>> user=&main.User{Username:"user01", Sex:"女", Age:18, AvatarUrl:"xxx.jpg"}
匿名字段
没有名字的字段
1: type User struct {2: Username string
3: Sex string
4: int5: string
6: }7:8: func main() {9: var user User
10: user.Username = "user01"11: user.Sex = "man"12: user.int = 100
13: user.string = "hello"14: fmt.Println(user)
15: }
1: >>> user=&main.User{Username:"user01", Sex:"女", Age:18, AvatarUrl:"xxx.jpg"}2:
结构体的嵌套
1: type Address struct {2: Province string
3: City string
4: }5:6: type User struct {7: Username string
8: Sex string
9: address Adress10: }11:12: func main() {13: user := &User{
14: Username:"user01",
15: Sex:"man",
16: address: Address{17: Province:"beijing",
18: City:"beijing",
19: },20: }21: fmt.Println(user)
22: fmt.Printf("user%#v", user)23: }
1: >>> &{user01 man {beijing beijing}}
2: user&main.User{Username:"user01", Sex:"man", address:main.Address{Province:"beijing", City:"beijing"}}
// 格式化输出时加上#会让输出按照近似go语言的数据结构来。
字段冲突的问题
优先使用主结构体里->没有就去嵌套结构体里面找字段可见性,大写表示公开访问,小写表示私有,不能跨包访问
tag是结构体的元信息
运行时可以通过反射的机制读出来
1: type User struct {2: Usename string `json:"username", db:"user_name"`3: Sex string `json:"sex"`4: Age int `json:"age"`
5: avatarUrl string
6: CreateTime string
7: }
1: package main2: import (
3: "encoding/json"
4: "fmt"
5: )6: type User struct {7: Username string `json:"username"`8: Sex string `json:"sex"`9: Score float3210: }11: func main() {12: user := &User{
13: Username:"user01",
14: Sex:"男",
15: Score:99.2,16: }17: data, _ := json.Marshal(user)18: fmt.Printf("json str:%s\n", string(data))19: }
1: >>> json str:{"username":"user01","sex":"男","Score":99.2}
20.面对对象2
方法的定义:和其他的语言不一样,go语言中不是使用class这个关键词,而且也没有class这个关键词
1: package main2: import "fmt"3: type People struct {4: Name string
5: Country string
6: }7: func (p People) Print() {8: fmt.Printf("name=%s country=%s\n", p.Name, p.Country)
9: }10: func (p People) Set(name string, country string) {11: p.Name = name
12: p.Country = country13: }14: func main() {15: var p1 People = People {16: Name : "people01",
17: Country: "china",
18: }19: p1.Print()20: p1.Set("people2", "USA")21: p1.Print()22: }
//注意结果是不变的
//函数不属于任何类型,方法属于特定的类型。
1: >>> name=people01 country=china
2: name=people01 country=china
指针类型作为接受者
1: package main2: import "fmt"3: type People struct {4: Name string
5: Country string
6: }7: func (p *People) Print() {8: fmt.Printf("name=%s country=%s\n", p.Name, p.Country)
9: }10: func (p *People) Set(name string, country string) {11: p.Name = name
12: p.Country = country13: }14: func main() {15: var p1 People = People {16: Name : "people01",
17: Country: "china",
18: }19: p1.Print()20: p1.Set("people02", "USA")21: // 语法糖(&p1).Set("people02", "USA")
22: p1.Print()23: }24: >>> name=people01 country=china
25: name=people2 country=USA
//注意结果已经改变了
1: >>> name=people01 country=china
2: name=people2 country=USA
匿名字段与继承
1: type Animal struct {2: Name string
3: Sex string
4: }5:6: func (a *Animal) Talk() {7: fmt.Printf("i\'m talking, i m %s\n", a.Name)
8: }9:10: type Dog struct {11: Feet string
12: *Animal13: }14:15: func (d *Dog) Eat() {16: fmt.Println("dog is eatting")
17: }18:19: func main() {20: var d *Dog = &Dog {21: Feet:"four feets",
22: Animal: &Animal {23: Name:"dog",
24: Sex:"公",
25: },26: }27: d.Name = "dog01"
28: d.Sex = "公"
29: d.Eat()30: d.Talk()31: }
1: >>> dog is eating2: i\'m talking, i m dog01
关于多重继承的冲突,与匿名字段的解决方法一样,通过指定的结构体与.运算符来调用。
Json序列化与反序列化
Json序列化
1: package main2:3: import (
4: "encoding/json"
5: "fmt"
6: )7:8: type Student struct {9: Id int10: Name string
11: Sex string
12: }13:14: type Class struct{15: Name string
16: Count int17: Student []*Student18: }19: func main() {20: classmate1 := &Class {21: Name :"101",
22: }23: count := 0
24: for i:=0;i<2;i++ {25: count += 1
26: stu := &Student {27: Name:fmt.Sprintf("stu%d", i ),
28: Sex : "man",
29: Id : i,
全部评论
请发表评论