文章目录
结构体
结构体是值类型传递
结构体的定义
package main
import "fmt"
type Student struct {
Name string
age int
}
func main() {
//结构体的声明
//var a Student
//var b Student = Student{}
//var b Student = Student{"as",12}
var c *Student = new(Student)
var d *Student = &Student{} //声明结构体指针,在方法中常用到
//注意这两种返回的是结构体指针
//var d *Student = &Student{"ss",22}
c.Name = "ss"
c.age = 12
d.age = 13
d.Name = "fyf"
fmt.Println(*c) //别忘了加*号
fmt.Println(*d)
}
结构体的小细节
不能,因为.的优先级比*高
结构体的所有字段(属性)在内存中是连续的
结构体的取别名和不同结构体的转换
package main
import "fmt"
type Fyf struct {
Name string
}
type FF struct {
Name string
}
type ok Fyf //将Fyf取别名
func main() {
var a Fyf
var b FF
a = Fyf(b) //注意两个结构体的字段必须相同
fmt.Println(a, b)
var c ok
c = ok(a) //go认为你取别名的结构体和原来的不一样,需要强制转换
fmt.Println(c)
}
结构体的json转换
目的是为了适应不同程序员的代码风格
package main
import (
"encoding/json"
"fmt"
)
type MOnster struct {
Name string `json:"名字"`//注意最外面的是反引号
Age int `json:"年龄"`
Address string `json:"地址"`
}
func main() {
a := MOnster{"泼猴", 5000, "花果山"}
jsonSr, err := json.Marshal(a)
if err != nil {
fmt.Printf("数据错误!", err)
} else {
fmt.Printf("jsonStr=%v", string(jsonSr))
}
}
方法
方法的使用
注意方法只能和自定义类型绑定,但是可以通过给基本数据类型取别名来实现对其他类型的绑定。
由于绑定了数据类型,当数据类型是值类型时,是值传递,若为引用类型,则为地址传递。
package main
import "fmt"
type FYF struct {
Name string
}
func (a FYF) print() {
fmt.Printf("b的名字为:%v", a.Name)
}
func main() {
b := FYF{"范宇峰"}
b.print()
}
运行结果:
int的方法实现
package main
import "fmt"
type in int
func (a in) print() {
fmt.Printf("这是f的测试数据:%v", a)
}
func main() {
var a in = 10
a.print()
}
实现了string方法则prinln会默认使用string方法
package main
import "fmt"
type Student struct {
Name string
Age int
}
func (s *Student) String() string {
str := fmt.Sprintf("名字为: %v,年龄为: %v", s.Name, s.Age)
//注意是Sprintf
return str
}
func main() {
var a Student
a.Name = "fyf"
a.Age = 20
fmt.Println(&a) //注意取址符
}
方法和函数的区别
方法和函数基本架构差不多,但是方法是绑定了相关的自定义类型,仅此而已。如下图test02函数和test03函数的区别。
小细节
方法的传递主要看方法的type
封装
工厂模式
图片
代码实现
model包代码
package model
type student struct {
Name string
Age float64
}
func NewStudent(n string, s float64) *student {
return &student{
Name: n,
Age: s,
}
}
主函数代码
package main
import (
"fmt"
"go笔记/封装/model"
)
func main() {
var stu = model.NewStudent("aa", 33)
fmt.Println(stu)
}
封装案例
person包代码
package person
import "fmt"
type person struct {
//这款将person首字母小写来进行封装
//age和sal也是小写,外包不能访问,所以可以通过绑定方法来进行访问和赋值
Name string
age int
sal float64
}
func Newperson(name string) *person {
return &person{
Name: name,
}
}
func (p *person) SetAge(age int) {
if age > 0 && age < 150 {
p.age = age
} else {
fmt.Println("年龄输入不正确!")
}
}
func (p *person) GetAge() int {
return p.age
}
func (p *person) SetSal(sal float64) {
if sal > 3000 && sal < 40000 {
p.sal = sal
} else {
fmt.Println("薪水输入不正确!")
}
}
func (p *person) GetSal() float64 {
return p.sal
}
主函数代码
package main
import (
"fmt"
"go笔记/封装/封装案例/person"
)
func main() {
p := person.Newperson("fyf")
p.SetSal(4000)
p.SetAge(20)
fmt.Println(p)
fmt.Println(p.Name, "age=", p.GetAge(), "sal=", p.GetSal())
}
运行结果
继承
继承主要通过匿名结构体来实现代码如下
package main
import "fmt"
type Stu struct {
Name string
Age int
Score float64
}
func (stu *Stu) Show() {
fmt.Println("Nmae=", stu.Name, "Age=", stu.Age, "Score", stu.Score)
}
func (s *Stu) SetScore(score float64) {
s.Score = score
}
type Pupil struct {
Stu //继承了Stu的属性和方法
}
func (p *Pupil) test() {
fmt.Println("小学生在考试!") //特有的方法
}
func main() {
p := &Pupil{}
p.Stu.Name = "fyf"
//p.Stu.Score = 100.0
p.Stu.Age = 20
p.Stu.SetScore(100)
p.Stu.Show()
p.test()
}
运行结果截图
继承的小细节
属性的访问遵循就近原则,如果b.age b结构体有age属性,则修改的是b的属性,如果没有,则访问匿名结构体中的属性
有时使用匿名结构体的指针来提高效率和直接修改结构体属性
可以在定义一个继承结构体时直接赋值
指针类型的匿名结构体的直接赋值
多重继承
多重继承就是一个结构体中嵌套了多个匿名结构体,尽量不要使用多重继承,会使得代码晦涩难懂。