面向对象编程 我们要明白的是,GO不是完全的是面向对象,他是包含有面向对象的特性,至于思想,在Java已经学习过了;略
构造结构体 构造体是值类型默认是拷贝
1 2 3 4 type person struct { name string age int }
使用构造体 1 2 3 4 5 6 7 8 type person struct { name string age int } var p person; p.name="saxon" p.age=18 fmt.Println(p)
1 2 3 4 5 6 7 var p person p.name = "saxon" p.age = 18 p1 := p p1.name = "saxon2" fmt.Println(p) fmt.Println(p1)
因为默认是值拷贝,所以我们的更改是不会互相影响的;包括属性是引用类型的数据也不会相互影响
申明结构体
直接使用
1 2 3 4 5 6 7 type person struct { name string age int } var p person; p.name="saxon" p.age=18
使用 var 变量名 结构体名=结构体名{}
1 2 3 4 5 6 7 8 type person struct { name string age int class map [string ]string } var p2 person=person{ "saxon" ,18 ,map [string ]string {"saxon" :"saxon" }, }
使用 *var 变量名 结构体名=new(结构体名)
*返回的是结构体指针,所以赋值可以使用p.name或者(p).name,都可以
1 2 3 4 var p3 *person = new(person) *p3.name="saxon" *p3.age=18 p3.class=map[string]string{"saxon":"saxon"}
使用 *var 变量名 结构体名=&变量名{}
1 var p4 *person = &person{"saxon" , 18 , map [string ]string {"saxon" : "saxon" }}
*最后两种返回的是指针类型,结构体指针访问属性的标准方式是:(结构体指针).field,但是go的底层也允许程序员使用结构体.field的方式访问变量
由于==.==的优先级大于*,所以 *p1.age=18,是无法通过编译的
结构体内存分配机制
正确的写法是进行一次强制类型转换go
方法 定义 1 2 3 4 5 6 7 8 9 10 11 12 type person11 struct { Name string `json:"ss"` } func (a person11) introduction () { fmt.Println("我的名字是" ,a.Name) } func main () { var p person11; p.Name="saxon" p.introduction() }
格式:func(结构体名字 结构体类型) 函数名字(函数参数)函数返回值
方法使用注意
方法只可以和绑定的结构体使用
不可以直接调用,也不可以 由其他的变量结构体来调用
方法的调用和传参机制 对象调用方法的时候,自己也会备份到方法里面
如果想要通过函数改变结构体的参数数据,那么调用这个方法的主体就要是一个指针,那样的话,我们修改的值就是指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package mainimport ( "fmt" ) type person11 struct { Name string `json:"ss"` } func (a *person11) introduction () { a.Name="sss" fmt.Println("我的名字是" ,a.Name) } func main () { var p person11; p.Name="saxon" fmt.Println(p) p.introduction() fmt.Println(p) }
如果想要实现一个结构体的toString()方法,那么只要在这个下面有一个String()函数就可以了
1 2 3 func (a person11) String () string { return "saxon" }
调用的主体是指针的话,那么方法内部就可以修改属性的值,不然的话就是值类型,修改不起作用
工厂模式 由于没有构造函数,所以我们使用工厂模式,实例化结构体
实际上和java的单例模式一样,解决我们的结构体的首字母是小写(私有)的情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package Demo2type Person12 struct { Name string } func GetPerson (name string ) (person Person12) { person = Person12{ name, } return } func main () {} func main () { per:=model.GetPerson("saxon" ) fmt.Println(per) }
这里的属性无论大小写,都可以通过工厂模式获得对象
*关于返回对象是指针的于一般对象的区别:返回值类型不同之处在于取值的方式,指针类型需要使用 * 号读取数据. 其次返回值指针判断空值更加容易简洁,t != nil.*
getter setter方法 封装了属性,所以我们要给外界一个接口,知道如何访问结构体里面的数据
例如:
1 2 3 func (person *person) SetName (name string ) { person.name = name }
1 2 3 4 5 func main () { per:=model.GetPerson("saxon" ) per.SetName("saxon2" ) fmt.Println(per) }
继承对象 由于没有extends这个关键字,所以我们要使用属于GO语言的继承,采用匿名结构体的方式实现继承机制
1 2 3 4 5 6 7 8 9 10 11 12 type Person struct { Name string } type Student struct { Person Age int } var stu util.Student = util.Student{ util.Person{"saxon" }, 18 , } fmt.Println(stu)
需要把所有的属性都公有化,就是首字母大写,不然无法直接使用,但是不要继承过多的结构体,相当于Java的单继承机制,我们尽量少继承一点
接口 在go里面没有implement这个关键字,所以一个结构体实现接口的方法就是实现接口的所有方法
当一个结构体实现了那个接口的所有方法,我们就可以说,他继承了或者是实现了一个接口;接口和Java里面的概念一样,不允许有方法体(Java8 以前)
接口本身不可以创建实体类,但是却可以实现多态;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 package mainimport "fmt" type human interface { run() skip() } type Student struct { name string age int } type Worker struct { name string age int } func (student Student) run () () { student.name = "saxon" fmt.Println(student.name + "在跑步" ) } func (student Student) skip () () { student.name = "saxon" fmt.Println(student.name + "在跳" ) } func (worker Worker) run () () { worker.name = "saxon" fmt.Println(worker.name + "在跑步(worker)" ) } func (worker Worker) skip () () { worker.name = "saxon" fmt.Println(worker.name + "在跳(worker)" ) } func main () { var stu human = Student{ "saxon" , 18 , } var worker human = Worker{ "mosong" , 18 , } stu.run() worker.run() }
可以和Java的使用方法一样创建多态,都是同一个类,但是实现不同的类,实现不同的功能
一个结构体可以实现多种的接口
自定义类型也可以使用和实现接口,我觉得这个可以实现Integer这些Java里面有的代表实体的类,写一些方法
1 2 3 4 5 6 7 8 type integer int func (i integer) run () { fmt.Println(i) } var i integer; i.run()
如果一个类型的结构被继承,或者继承其他接口,那么这个接口的实现类就是实现所有的方法;如果一个类继承两个接口,那么这两个接口就必须不能有一样的方法
接口实现类数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package mainimport "fmt" type Usb interface { start() } type Phone struct { name string } type Watch struct { name string } func (phone Phone) start () { fmt.Println(phone.name) } func (watch Watch) start () { fmt.Println(watch.name) } func main () { phone := Phone{ "iphone" , } watch := Watch{ "iWatch" , } var usbs []Usb = []Usb{ phone, watch, } usbs[0 ].start() usbs[1 ].start() }
实际上我们实现的是一个接口的切片,我们可以把都是实现了这个接口的实现类,在一个数组或者切片里面
断言 我们使用的变量太多,我们不知道他的实际类型是什么,所以我们要使用断言来对我们的数据类型进行一个判断
1 2 3 4 5 6 7 8 9 10 11 type assert interface {}type Demo17 struct {} func main () { b:=1 var a assert; a=b boolean:=a.(int32 ) fmt.Println(boolean) }
使用步骤:
创建一个空的接口,这个接口将要接收我们要判断的类型,如果是这个类型,那么接受的变量就会被赋值,如果不是,那么就会退出,报错;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package mainimport "fmt" type assert interface {}type Demo17 struct { name string } func main () { var x assert; y:=Demo17{ "saxon" , } x=y a:=x.(int ) fmt.Println(a) }
如果我们要使用断言并且让他在失败时不中断,我们就使用if ,结构来获得属性返回我们想要的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package mainimport "fmt" type test17 struct { name string } type assert17 interface {}func main () { a := test17{ "saxon" , } var x assert17 x=a if y,ok:=x.(int );ok{ fmt.Println(y) }else { fmt.Println("error" ) } go }
核心
1 2 y, ok := x.(test17) data,bool :=对象.(数据类型)
其中前面的data代表着数据,如果对象是这个数据类型的时候,这个就是对象的数据,如果不是的话,他会是数据类型里面的默认值
接下来进行一个实践
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package mainimport "fmt" func main () { a:=true b:="ss" check(a,b) } func check (items ...interface {}) { for index, value := range items { switch a := value.(type ) { case bool : fmt.Printf("第%d个是%T类型" , index, a) case string : fmt.Printf("第%d个是%T类型" , index, a) } } }
判断一个对象的实体是否是某一个类型,除了可以在数据类型那里写实际的类型,还可以使用type代替,可以在switch内部使用参数.(type) ,里面的type就是type;但是仅仅局限于我们的switch循环里面
在switch里面可以使用这种方法直接获得对象的数据类型
第一个简单的实践项目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 package mainimport ( "fmt" "strconv" ) var manger *Mangerfunc init () { manger = &Manger{} manger.list = make ([]Customer, 10 ) } func main () { manger.start() } type Manger struct { list []Customer } type Customer struct { name string sex string age int64 telephone string email string } func (manger *Manger) start () { fmt.Println("---------------客户管理页面-------------" ) fmt.Println("---------------(1)添加用户-------------" ) fmt.Println("---------------(2)查询用户-------------" ) fmt.Println("---------------(3)删除用户-------------" ) fmt.Println("---------------(4)修改用户-------------" ) fmt.Println("---------------(5)退出系统-------------" ) fmt.Println("-----------请选择你要使用的功能-------------" ) key := 0 fmt.Scanln(&key) switch key { case 1 : manger.AddCustomer() manger.start() case 2 : manger.SearchAllCustomer() manger.start() case 3 : manger.DeleteCustomer() manger.start() case 4 : manger.AlertCustomer() manger.start() case 5 : fmt.Println("-----------谢谢使用--------------" ) } } func (manger *Manger) AddCustomer () (customer Customer) { fmt.Println("请输入信息添加用户,使用空格分开" ) var name, sex, telephone, email string var age int64 fmt.Scanln(&name, &sex, &age, &telephone, &email) customer = Customer{ name, sex, age, telephone, email, } fmt.Println("-----------添加成功-------------" ) manger.list = append (manger.list, customer) return } func (manger *Manger) SearchAllCustomer () { fmt.Println("-----------客户信息-----------" ) for _, value := range manger.list { if value.name != "" { fmt.Println("姓名:" + value.name) fmt.Println("性别:" + value.sex) fmt.Println("年龄:" , value.age) fmt.Println("电话号码:" , value.telephone) fmt.Println("邮箱:" , value.email) fmt.Println() } } } func (manger *Manger) DeleteCustomer () { var name string fmt.Println("输入你要删除的用户名" ) fmt.Scanln(&name) for index, value := range manger.list { if value.name == name { manger.list = append (manger.list[:index], manger.list[index+1 :]...) } } } func (manger *Manger) AlertCustomer () { fmt.Println("输入你要修改的用户名" ) name := "" fmt.Scanln(&name) for index, value := range manger.list { if value.name == name { fmt.Println("请输入你要修改的信息项目和修改后的信息" ) ctype := "" info := "" fmt.Scanln(&ctype) switch ctype { case "name" : value.name = info case "age" : age, _ := strconv.ParseInt(info, 10 , 32 ) value.age = age case "sex" : value.sex = info case "telephone" : value.telephone = info case "email" : value.email = info case "Q" ,"q" : } } else { if index==len (manger.list)-1 { fmt.Println("没有这个用户请再次确认信息" ) } } } }