go语言没有类,只有结构体,等同于类(class)
//定义一个结构体(类)
type Book struct { //如果类首字母大写,表示其他包也能够访问
Title string //如果类属性首字母大写,表示该属性公有,否则为私有
auth string
}
//创建实例
func main() {
// 方式一
var bk1 Book = Book{title: "xixi",auth: "flandre"}
// 方式二
bk2 := Book{title: "haha",auth: "flandre"}
// 方式三
var bk3 *Book = new(Book)
(*bk3).auth = "flandre"
// 方式四
var bk3 *Book = &Book{title: "heihei",auth: "flandre}
}
方式三四返回的都是结构体指针。但go也支持bk3.auth
type Point struct {
x int
y int
}
type Rect struct {
leftUp,rightDown Point
}
func main() {
r1 := Rect{Point{1,2},Point{3,4}}
// r1的四个点内存连续
fmt.Printf("r1.leftUp.x地址 = %p r1.leftUp.y地址 = %p\n r1.rightDown.x地址 = %p r1.rightDown.y地址 = %p",
&r1.leftUp.x,&r1.leftUp.y,&r1.rightDown.x,&r1.rightDown.y)
//r1.leftUp.x地址 = 0xc000012200 r1.leftUp.y地址 = 0xc000012208
//r1.rightDown.x地址 = 0xc000012210 r1.rightDown.y地址 = 0xc000012218
}
两个结构体之间相互转换,需要字段完全相同
type A struct {
Num int
}
type B struct {
Num int
}
func main() {
var a A
var b B
a = A(b)
fmt.Println(a,b)
}
结构体进行type重新定义(相当于取别名),Golang认识是新的数据类型,但是相互可以强转
type Student struct {
Name string
Age int
}
type Stu Student
type integer int
func main() {
var stu1 Student
var stu2 Stu
stu2=Stu(stu1)
fmt.Println(stu1,stu2)
var i integer = 10
var j int = 20
j = int(i)
fmt.Println(i,j)
}
结构体的每个字段上,可以写一个tag,该tag可以通过反射机制获取,使用场景多为序列化和反序列化
type Monster struct {
Name string `json:"name"` // tag `json:"name"`
Age int `json:"age"`
Skill string `json:"skill"`
}
func main() {
monster := Monster{"翠花",20,"xixi"}
jsonStr,err := json.Marshal(monster)
if err != nil{
fmt.Println("json处理错误")
} // tag前:{"Name":"翠花","Age":20,"Skill":"xixi"}
fmt.Println("jsonStr:",string(jsonStr))
} // tag后:{"name":"翠花","age":20,"skill":"xixi"}
//方法声明
func (recevier type) methodName(参数列表) (返回值列表) {
方法体
return 返回值
}
type Person struct {
Name string
}
func (p Person) speak() {
fmt.Println(p.Name)
}
func main() {
var p Person
p.Name = "flandre"
p.speak() // My name is flandre
}
type Person struct {
Name string
Age int
}
// Person实现方法String()
func (this *Person) String() string {
str := fmt.Sprintf("Name=[%v],Age=[%v]",this.Name,this.Age)
return str
}
func main() {
pp := Person{
Name: "flandre",
Age: 20,
}
fmt.Println(pp) // {flandre 20}
fmt.Println(&pp) // Name=[flandre],Age=[20]
}
方法和函数的区别
Golang的结构体没有构造函数,通常使用工厂模式解决这个问题
工厂模式:实现跨包创建结构体实例
type student struct {
Name string
age int
}
// 因为student结构体首字母小写,所以私有(只能在本包使用)
// 使用工厂模式解决
func NewStudent(n string,a int) *student {
return &student{
Name: n,
age: a,
}
}
// age首字母小写,也需要提供一个方法
func (this *student) GetAge() int {
return this.age
}
**封装:**结构体、属性小写(私有化),提供工厂模式,Set、Get方法
type Hero struct {
name string
Ad int
Level int
}
func (this *Hero)GetName() string {
return this.Name
}
func (this *Hero)SetName(newName string) {
this.Name = newName
}
继承:
type Human struct {
name string
sex string
}
// 子类
type Superman struct {
Human //该类继承了Human
level int
}
// 多继承情况下必须指定继承那个结构体的属性
type A struct {
Name string
Age int
}
type B struct {
Name string
id int
}
type C struct {
A
B
}
func main() {
var c C
c.A.Name = "flandre"
}
Golang中多态的特性主要是由接口实现的
type AnimalIF interface { //本质是一个指针
Sleep()
GetColor() string // string是返回值
}
//具体的类
type Cat struct {
color string
}
func (this *Cat) Sleep() {
fmt.Println("Cat is Sleep")
}
func (this *Cat) GetColor() string {
return this.color
}
func showAnimal(animal AnimalIF) {
animal.Sleep() //多态
fmt.Println(animal.GetColor())
}
func main() {
var animal AnimalIF //接口的数据类型
animal = &Cat{"Green"}
animal.Sleep() //调用cat的sleep方法 // Cat is Sleep
fmt.Println(animal.GetColor()) // Green
//cat := Cat{"Green"}
//showAnimal(&cat)
}
type A interface {
Start()
}
type B interface {
End()
}
type C struct {
}
func (this *C) End() {
fmt.Println("游戏概述")
}
func (this *C) Start() {
fmt.Println("芜湖!起飞!")
}
func main() {
var c C
var a1 A = &c
var b1 B = &c
a1.Start() // 芜湖!起飞!
b1.End() // 游戏概述
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zJ6gPJeW-1645582469622)(C:\Users\11140\Desktop\md笔记\images\接口vs继承.png)]
上面的代码中有
if person,ok := arg.(Person);ok{
person.Say()
}
例1:
//interface{}是万能数据类型
func myFunc(arg interface{}) {
fmt.Println("万能类型")
fmt.Println(arg)
//interface{}该如何区分,其实引用的数据类型是什么?
//给interface{}提供了“断言”机制
value,ok := arg.(string)
if !ok {
fmt.Println("arg is not string type")
}else {
fmt.Println("arg is string type,value = ",value)
}
}
type Book struct {
auth string
}
func main() {
book := Book{"Golang"}
myFunc(book)
myFunc(100)
myFunc("abc")
myFunc(3.14)
}
例2:循环判断传入参数的类型
func TypeJudge(arg ...interface{}) {
for index,value := range arg {
switch value.(type) {
case bool:
fmt.Printf("arg %d is bool type,value is %v\n",index,value)
case string:
fmt.Printf("arg %d is string type,value is %v\n",index,value)
case int,int64:
fmt.Printf("arg %d is int type,value is %v\n",index,value)
case float32,float64:
fmt.Printf("arg %d is float type,value is %v\n",index,value)
case nil:
fmt.Printf("arg %d is nil type,value is %v\n",index,value)
case Student:
fmt.Printf("arg %d is Student type,value is %v\n",index,value)
case *Student:
fmt.Printf("arg %d is *Student type,value is %v\n",index,value)
default:
fmt.Printf("arg %d is unknown type,value is %v\n",index,value)
}
}
}
func main() {
var n1 float32 = 1.1
var n2 float64 = 1.2
var n3 int = 30
var name string = "flandre"
var ty bool = true
stu1 := Student{}
stu2 := &Student{}
TypeJudge(n1,n2,n3,name,ty,stu1,stu2)
}
//arg 0 is float type,value is 1.1
//arg 1 is float type,value is 1.2
//arg 2 is int type,value is 30
//arg 3 is string type,value is flandre
//arg 4 is bool type,value is true
//arg 5 is Student type,value is {}
//arg 6 is *Student type,value is &{}