go结构体
go支持面向对象编程(OOP),struct是值传递
//struct变量都有默认值
type Cat struct {
Name string
Age int
Color string
}
var cat Cat
cat.Name = "micky"
cat.Age = 3
cat.Color = "Red"
fmt.Println(cat)
fmt.Println(cat.Name)
fmt.Println(&cat) //cat的地址
- 结构体的名字如果是大写代表可以被其他包使用
- 如果属性是指针,map,切片需要先make才能使用
type Person struct {
Name string
arr [3]int
prt *int
slice []int
maps map[string]string
}
//第一种定义对象
var man Person
man.ptr = new(int)
man.slice = make([]int, 10)
man.slice[0] = 1
man.maps = make(map[string]string)
man.maps["key"] = "value"
// 第二种定义对象
man := Person{"elle", 18}
//第三种定义对象
var man *Person = new(Person)
(*man).Name = "Bella"
(*man).Age = 23
man.Age = 33 //同上种写法
fmt.Println(*man)
//第四种定义对象
var man *Person = &Person{"elle", 18}
(*man).Age = 23
man.Age = 33 //同上种写法,为方便开发者,底层仍是延续上种方式
- 结构体之间强转需要元素的类型和名字完全一致
type Cat struct {
Num int
}
type Dog struct {
Num int
}
func main() {
var cat Cat
var dog Dog
dog = Cat (cat) //强制转换
}
- 结构体tag
import "encoding/json"
//json序列号成json
cat := Cat{"mimi", 3, "yellow"}
json_cat,_ := json.Marshal(cat)
fmt.Println(json_cat) //返回的是byte[]切片类型
fmt.Println(string(json_cat)) //返回的是Name大写首字母的json格式
//解决方案:打tag
type Cat struct {
Name string `json: "name"`
Age int `json: "age"`
Color string `json: "color"`
}
go方法
方法是作用在指定类型的,自定义类型都可以有方法
定义:func (cat Cat) test(参数列表) 返回值类型 {}
主函数里的p对象传给方法时同函数都是值传递,不会改变主函数的值
- 自定义类型
type interger int
func (i interger) print() {
fmt.Println(i)
}
func main(){
var i interger = 10
i.print()
}
- 方法和函数的区别
函数:传递的参数必须和定义时保持一致
方法:传递的参数必须和定义时可以不一致
go工厂模式
go里没有构造函数,用工厂模式替代
使用场景:结构体首字母小写,本不能被其他包使用,但仍有被其他包使用的需求
解决办法:在结构体外包一层函数,指向这个结构体
在其他包的main函数调用
如果结构体里的元素score是小写的,即使外面包了一层NewStudent仍不能被其他包调用,若想使用小写的结构体内元素还需要单独给元素包一层
在其他文件调用时
go三大特征
封装:就是把抽象出的字段和对字段的操作封装在一起
封装好处:隐藏实现细节
继承:通过匿名结构体实现
type Student struct {
Name string,
Age int,
Score int,
}
type Pupil struct {
Student //继承Student
}
type Graduate struct {
Student //继承Student
}
// 使用指针可以直接修改main里定义的对象
func (stu *Student) ShowInfo() {
fmt.Printf("name=%v,age=%v,score=%v", stu.Name, stu.Age, stu.Score)
}
func (stu *Student) setScore(score int) {
stu.Score = score
}
func (p *Pupil) testing() {
fmt.Println("pupil is testing...")
}
func (p *Graduate ) testing() {
fmt.Println("Graduate is testing...")
}
func main() {
pupil := Pupil{"mike", 7, 0}
pupil.Student.Name = "jack"
pupil.Name = "amber"
//这2种赋值不等价,因为如果Pupil类里还有个Name元素是允许的
pupil.testing()
pupil.setScore(90)
}
- 同时继承多个结构体
type Goods struct {
Name string
Price string
}
type Brand struct {
Name string
Address string
}
type TV struct {
Goods
Brand
}
type TV2 struct {
*Goods
*Brand
}
func main() {
// 注意末尾的,不要忘记
tv1 := TV{Goods{"tv", 1000}, Brand{"haier", "china"},}
tv2 := TV{&Goods{"tv", 1000}, &Brand{"haier", "china"},}
// 先取Goods的地址,再拿到值
fmt.Println(*tv2.Goods)
}
go接口
type 接口名 interface {
方法1 //不需要实现
方法2
}
func (t 自定义类型)方法1(参数列表) 返回值列表{
实现
}
type Usb interface {
Start()
Stop()
}
type Phone struct {
}
type Camera struct {
}
type Computer struct {
}
// phone
func (p Phone) Start(){
fmt.Println("Phone starting...")
}
func (p Phone) Stop(){
fmt.Println("Phone stoping...")
}
// camera
func (c Camera ) Start(){
fmt.Println("Camera starting...")
}
func (c Camera ) Stop(){
fmt.Println("Camera stoping...")
}
//computer
func (com Computer) work(usb Usb){
usb.Start()
usb.Stop()
}
// assert
func (p Phone) Call() {
fmt.Println("Phone calling...")
}
func main(){
computer := Computer{}
phone := Phone{}
camera := Camera{}
//谁实现了interface就可以作为参数传递
computer.work(phone)
computer.work(camera)
//多态数组,通过接口实现一个数组内存放多种类型数据
var arr [3]usb
usb[0] = Phone{}
usb[1] = Camera{}
}
- 接口注意事项
- 接口不可以实例化,但可以定义一个实现了该方法的结构体指向它
- 接口中的每一个方法都要实现
- 自定义类型(type interger int)也可以实现接口方法
- 接口中不允许有任何变量
- 接口直间可以相互继承,若想实现子接口必须实现父接口
- interface是引用类型
- interface{}是一种数据类型,所有类型都实现了空接口
多态:通过接口实现,接口是对继承的补充
go断言
type Point struct{
x int
y int
}
func main(){
var a interface{}
a = Point(1,2)
var b Point
b = a //不可以
b = a.(Point) //断言
// 断言判断
b, flag = a.(Point)
if flag {
fmt.Println("convert success")
}else{
fmt.Println("convert fail")
}
}
🤭:判断a是否是指向Point类型的变量,如果是则将a转换为Point赋值给b,不是则报错
func (com Computer) work(usb Usb){
usb.Start()
phone,ok := usb.(Phone)
if ok {
phone.Call()
}
usb.Stop()
}