Go_面向对象
GO语言中没有class的定义, 但是struct实现了class的功能(方法, 继承等)
struct声明
type 标识符 struct{
field1 type
field2 type
}
//例子
type Student struct{
Name string
Age int
Score int
}
// 新名字,
定义了一种新的类型, 其中字段与Student相同
type Stu Student
type inter int
声明定义及访问
声明
var stu student
var stu *Student = new(Student) // 返回指针
var stu *Student = &Student{字段:值,字段:值}// 返回指针
访问
// 通过.的方式去取值和设置值
func main() {
var stu Student
stu.Name = "自由"
stu.Age = 18
stu.Score = 60
fmt.Println(stu)
}
ps:
- 无论变量是指针类型还是非指针类型都可以直接使用.的方式去操作
- 结构体在内存中的布局是连续的, 是指类型, 函数传递要传递指针
- struct没有构造函数, 一般可以使用工厂模式来解决
func NewStudent(name string, age int) *Student{ return &student{ Name:name, Age: age } }
Tag : 我们可以为struct中的每个字段, 写上一个tag.这个tag可以通过反射机制获取到
type Student struct{
Name string "this is name field"
Age int "this is age field"
}
方法
go中的方法作用域特定类型的变量上, 因此自定义类型都可以有方法, 而不仅仅是struct
定义
func (object type) methodname (args) ( rets ){
// 方法体
}
示例
type Student struct{
Name string
Age int
Score int
sex int
}
func (p Student) init(name string, age int, score int){
p.Name = name
p.Age = age
p.Score = score
}
func main(){
var stu Student
stu.init("stu", 18, 100)
}
不过上面的例子中并不会对stu产生影响, 因为p是stu的备份, 我们可以修改方法,使其接收指针
func (p *Student) init(name string, age int, score int){
(*p).Name = name
(*p).Age = age
(*p).Score = score
}
func main(){
var stu Student
stu.init("stu", 18, 100)
}
向上面这种不断的取值很麻烦, 好在go帮我们解决了此事, 当传入的是个指针时我们可以直接通过.的方式去去柱子
func (p *Student) init(name string, age int, score int){
p.Name = name
p.Age = age
p.Score = score
}
// 可以改变调用者的值
继承
结构体中的匿名字段, 变量可以直接去访问匿名变量的字段
type Animal struct{
Name string
Age int
}
type Dog struct{
Animal
Colour string
}
func main(){
var dog Dog
dog.Name = "旺财"
dog.Age = 2
dog.Colour = "斑点"
fmt.Println(dog.Name, dog.Age, dog.Colour)
}
名称冲突
当结构体中的字段与其内部匿名字段中的字段同名时, 默认访问的是自己的
当两个匿名字段中的字段相同时
type Sitiaotui struct{
Name string
}
type Dog struct{
Animal
Sitiaotui
Colour string
}
func main(){
var dog Dog
dog.Animal.Name = "旺财"
dog.Age = 2
dog.Colour = "斑点"
fmt.Println(dog.Animal.Name, dog.Age, dog.Colour)
}
方法的继承同字段相同
访问控制
属性及方法的首字母, 同包
接口
接口也是一种类型, 接口的应用相当的灵活.
接口规定了了实现了他的类必须定义的方法, 而在Go中不需要声明实现接口, 只要实现了该接口中的方法就可以认为实现了该接口.
接口定义
Interface类型可以定义一组方法, 但是这些不需要实现. 并且interface不能包含任何变量
type Test interface{
function(args)(rets)
}
实现
结构体有指定方法就实现了该接口, 接口变量是个指针类型
一个类型实现了一个接口, 这个类型就可以给这个接口赋值
package main
import "fmt"
type Student struct{
Name string
Age int
Score int
sex int
}
type Test interface {
print()
}
func (p Student) print(){
fmt.Println(p)
}
func main(){
var t Test
var stu Student = Student{
Name :"lihua",
Age : 18}
t = stu // 可以赋值给接口类型
t.print()
}
接口的嵌套
type Writer interface{
Write()
}
type Reader interface{
Read()
}
type ReadWrite interface{
Reader
Writer
}
func Test(rw ReadWriter){
rw.Read()
rw.Write()
}
空接口 interface{}: 任何类型都可以赋值给空接口类型的变量
String()方法 : Print调用的方法
package main
import "fmt"
type Student struct{
Name string
Age int
Score int
sex int
}
func (p Student) String() string {
return fmt.Sprintf("%s,%d, %d",p.Name, p.Age, p.sex)
}
func main(){
var stu Student = Student{
Name :"lihua",
Age : 18}
fmt.Println(stu) // lihua,18, 0
}
类型断言
将一个接口变量转换成类型
当确定类型时:
func main(){
var a interface{}
var b int
a = b
c := a.(int) // 转回其他类型
fmt.Printf("%d %T", c,c)
}
当不确定类型时, 带有错误信息
func main(){
s := 100
if v, ok := interface{}(s).(string); ok {
fmt.Println(v)
}else{
fmt.Println("不能转")
}
}
上面这种也可以判断是否实现了某个接口
type Test interface {
print()
}
func (p Student) print(){
fmt.Println(p)
}
func main(){
var stu Student = Student{
Name :"lihua",
Age : 18}
t, ok := interface{}(stu).(Test)
fmt.Println(t, ok, stu)
}
返回具体类型
package main
import (
"fmt"
)
type Element interface {}
func main() {
var e Element = 100
switch value := e.(type) {
case int:
fmt.Println("int", value)
case string:
fmt.Println("string", value)
default:
fmt.Println("unknown", value)
}
}

浙公网安备 33010602011771号