一、结构体
1.Golang并不是纯粹的面向对象语言,但支持面向对象特性
2.Golang中没有class,结构体struct与其他语言的class同等地位
3.Golang面向对象非常简洁,去掉传统的方法重载,构造函数,隐藏this指针等
4.Golang中面向接口编程非常重要,耦合性低
5.结构体是值类型,结构体是自定义数据类型,结构体变量是具体的实际的变量
6.结构体字段如果是指针、slice、map默认零值是nil,即没有分配空间,使用时一定要先make
package main
import (
"encoding/json"
"fmt"
)
//结构体声明,字段在内存中的地址是连续的
type Person struct { //每次type都是重新定义一次,相当于新的数据类型,但可以强转
Name string `json:"name"`
Age int
Scores [3]float64
ptr *int //默认nil
slice []int //默认nil
map1 map[string]string //默认nil
}
func main() {
//创建结构体实例第一种方式
var person Person //var a int
person.Name = "小红"
person.Age = 13
fmt.Println(person)
fmt.Println("人的名字:", person.Name)
//第二种方式
p2 := Person{"小王", 15, [3]float64{88, 98, 99}, nil, nil, nil}
pp2 := Person{Name : "小王",Age:15} //不依赖字段定义顺序
fmt.Println(p2)
//第三种方式
p3 := new(Person) //p3是一个结构体指针
(*p3).Name = "小张" //标准赋值方法
p3.Name = "小赵" //这样也可以,因为go设计者为了程序员方便,底层进行了处理
(*p3).Age = 16
fmt.Println(*p3)
fmt.Println((*p3).Age) //()必须加,因为"."运算符优先级高
//第四种方式
p4 := &Person{} //p4是一个结构体指针
(*p4).Name = "小刘"
p4.Name = "小关" //与第三种方式一致
(*p4).Age = 18
fmt.Println(*p4)//因为是指针所以要取值运算符
//使用tag标签,使json字段变成小写
jsonStr, _ := json.Marshal(person)
fmt.Println(string(jsonStr))
//工厂模式,结构体在model包中访问私有变量
var student = model.NewStudent("Tom", 19)
fmt.Println(*student)
fmt.Println(student.GetName())
}
package model
type student struct {
name string
age int
}
func NewStudent(n string, a int) *student {
return &student{n, a}
}
func (s *student) GetName() string {
return s.name
}
二、方法
package main
import "fmt"
type Person struct {
Name string
Age int
}
//表示Person类型绑定一个test方法
//p 是一个实例
func (p Person) test() { //person调用此函数,person进行拷贝,值拷贝
p.Name = "小王"
fmt.Println(p.Name)
}
func (p *Person) test01() {
p.Name = "Jack"
fmt.Println(p.Name)
}
func (p *Person) String() string {
//编译器底层做了处理 p.Name 等价于 (*p).Name
str := fmt.Sprintf("Name=%v,Age=%v", p.Name, p.Age)
return str
}
func main() {
var person Person
person.Name = "小张"
person.Age = 15
//决定是值拷贝还是地址拷贝是看方法和哪个类型绑定
person.test()
(&person).test() // 编译器特殊处理,本质上也是值拷贝
fmt.Println(person) //输出小张
person.test01() //等价于(&person).test01(),编译器特殊处理
(&person).test01() //正常调用方式
fmt.Println(person) //输出 Jack
//如果重写了指针类型 *Person 的 String() 方法,就会自动调用。
fmt.Println(&person) //自动调用 String()
//标准 (&person).String(),但编译器底层做了处理
str := person.String()
fmt.Println(str)
}