2396 字
12 分钟
base04-递归+结构体

base04-递归+结构体#

递归#

// 永远不要高估自己!
// 递归:函数自己调用自己!
// 递归适合处理那种问题相同\问题的规模越来越小的场景
// 递归一定要有一个明确的退出条件
// 3! = 3*2*1 = 3*2!
// 4! = 4*3*2*1 = 4*3!
// 5! = 5*4*3*2*1 = 5*4!
// 计算n的阶乘
func f(n uint64) uint64 {
if n <= 1 {
return 1
}
return n * f(n-1)
}
// 上台阶的面试题
// n个台阶,一次可以走1步,也可以走2步,有多少种走法。
func taijie(n uint64) uint64 {
if n == 1 {
// 如果只有一个台阶就一种走法
return 1
}
if n == 2 {
return 2
}
return taijie(n-1) + taijie(n-2)
}
func main() {
// ret := f(7)
// fmt.Println(ret)
ret := taijie(4)
fmt.Println(ret)
}

02、type#

// 自定义类型和类型别名
// type后面跟的是类型
type myInt int // 自定义类型
type yourInt = int // 类型别名
func main() {
var n myInt
n = 100
fmt.Println(n)
fmt.Printf("%T %d\n", n, n)
var m yourInt
m = 100
fmt.Println(m)
fmt.Printf("%T\n", m)
var c rune
c = ''
fmt.Println(c)
fmt.Printf("%T\n", c)
}

03、结构体1#

// 结构体
type person struct {
name string
age int
gender string
hobby []string
}
func main() {
// 声明一个person类型的变量p
var p person
// 通过字段赋值
p.name = "周林"
p.age = 9000
p.gender = "男"
p.hobby = []string{"篮球", "足球", "双色球"}
fmt.Println(p)
// 访问变量p的字段
fmt.Printf("%T\n", p)
fmt.Println(p.name)
var p2 person
p2.name = "理想"
p2.age = 18
fmt.Printf("type:%T value:%v\n", p2, p2)
// 匿名结构体:多用于临时场景
var s struct {
x string
y int
}
s.x = "嘿嘿嘿"
s.y = 100
fmt.Printf("type:%T value:%v\n", s, s)
}

04、结构体2#

// 结构体是值类型
type person struct {
name, gender string
}
// go语言中函数传参数永远传的是拷贝
func f(x person) {
x.gender = "女" // 修改的是副本的gender
}
func f2(x *person) {
// (*x).gender = "女" // 根据内存地址找到那个原变量,修改的就是原来的变量
x.gender = "女" // 语法糖,自动根据指针找对应的变量
}
func main() {
var p person
p.name = "周林"
p.gender = "男"
f(p)
fmt.Println(p.gender) // 男
f2(&p) // ox1241ac3
fmt.Println(p.gender) // 女
// 结构体指针1
var p2 = new(person)
(*p2).name = "理想"
p2.gender = "保密"
fmt.Printf("%T\n", p2)
fmt.Printf("%p\n", p2) // p2保存的值就是一个内存地址
fmt.Printf("%p\n", &p2) // 求b2的内存地址
// 2. 结构体指针2
// 2.1 key-value初始化
var p3 = &person{
name: "元帅",
}
fmt.Printf("%#v\n", p3)
// 2.2 使用值列表的形式初始化, 值的顺序要和结构体定义时字段的顺序一致
p4 := &person{
"小王子",
"男",
}
fmt.Printf("%#v\n", p4)
}

05、 打印#

//
func main() {
var a int
a = 100
b := &a
fmt.Printf("type a:%T type b:%T\n", a, b)
// 将a的十六进制内存地址打印出来
fmt.Printf("%p\n", &a)
fmt.Printf("%p\n", b) // b的值
fmt.Printf("%v\n", b)
fmt.Printf("%p\n", &b) // b的内存地址
}

06、结构体#

// 结构体占用一块连续的内存空间
type x struct {
a int8 // 8bit => 1byte
b int8
c int8
}
func main() {
m := x{
a: int8(10),
b: int8(20),
c: int8(30),
}
fmt.Printf("%p\n", &(m.a))
fmt.Printf("%p\n", &(m.b))
fmt.Printf("%p\n", &(m.c))
}

07、 构造函数#

// 构造函数
type person struct {
name string
age int
}
type dog struct {
name string
}
// 构造函数:约定成俗用new开头
// 返回的是结构体还是结构体指针
// 当结构体比较大的时候尽量使用结构体指针,减少程序的内存开销
func newPerson(name string, age int) *person {
return &person{
name: name,
age: age,
}
}
func newDog(name string) dog {
return dog{
name: name,
}
}
func main() {
p1 := newPerson("元帅", 18)
p2 := newPerson("周林", 9000)
fmt.Println(p1, p2)
d1 := newDog("周林")
fmt.Println(d1)
}

08、方法是作用于特定类型的函数#

// 方法
// 标识符:变量名 函数名 类型名 方法名
// Go语言中如果标识符首字母是大写的,就表示对外部包可见(暴露的,公有的).
// dog 这是一个狗的结构体
type dog struct {
name string
}
type person struct {
name string
age int
}
func newPerson(name string, age int) *person {
return &person{
name: name,
age: age,
}
}
// 构造函数
func newDog(name string) dog {
return dog{
name: name,
}
}
// 方法是作用于特定类型的函数
// 接受者表示的是调用该方法的具体类型变量,多用类型名首字母小写表示
func (d dog) wang() {
fmt.Printf("%s:汪汪汪~", d.name)
}
// 使用值接收者:传拷贝进去
// func (p person) guonian() {
// p.age++
// }
// 指针接收者:传内存地址进去
func (p *person) zhenguonian() {
p.age++
}
func (p *person) dream() {
fmt.Println("不上班也能挣钱!")
}
func main() {
// d1 := newDog("zhoulin")
// d1.wang()
p1 := newPerson("元帅", 18)
// p1.wang()
fmt.Println(p1.age) // 18
// p1.guonian()
fmt.Println(p1.age) // 18
p1.zhenguonian()
fmt.Println(p1.age) // ?
p1.dream()
}

09、#

// 给自定义类型加方法
// 不能给别的包里面的类型添加方法,只能给自己包里的类型添加方法
type myInt int
func (m myInt) hello() {
fmt.Println("我是一个int")
}
func main() {
m := myInt(100)
m.hello()
}

10、结构体遇到的问题#

// 结构体遇到的问题
// 1. myInt(100)是个啥?
type myInt int
func (m myInt) hello() {
fmt.Println("我是一个int")
}
type person struct {
name string
age int
}
func main() {
// 声明一个int32类型的变量x,它的值是10
// 方法1:
// var x int32
// x = 10
// 方法2:
// var x int32 = 10
// 方法3:
// var x = int32(10)
// 方法4:
// x := int32(10)
// fmt.Println(x)
// 声明一个myInt类型的变量m,它的值是100
// 方法1:
// var m myInt
// m = 100
// 方法2:
// var m myInt = 100
// 方法3:
// var m = myInt(100)
// 方法4
// m := myInt(100) // 强制类型转换
// fmt.Println(m)
// m := myInt(100)
// m.hello()
// 问题2:结构体初始化
// 方法1:
var p person // 声明一个person类型的变量p
p.name = "元帅"
p.age = 18
fmt.Println(p)
var p1 person
p1.name = "周林"
p1.age = 9000
fmt.Println(p1)
// 方法2:
s1 := []int{1, 2, 3, 4}
m1 := map[string]int{
"stu1": 100,
"stu2": 99,
"stu3": 0,
}
fmt.Println(s1, m1)
// 键值对初始化
var p2 = person{
name: "冠华",
age: 15,
}
fmt.Println(p2)
// 值列表初始化
var p3 = person{
"理想",
100,
}
fmt.Println(p3)
}
// 问题3:为什么要有构造函数
func newPerson(name string, age int) person {
// 别人调用我,我能给她一个person类型的变量
return person{
name: name,
age: age,
}
}
// func newPerson(name string, age int) *person {
// // 别人调用我,我能给她一个person类型的变量
// return &person{
// name: name,
// age: age,
// }
// }

11、sms函数版#

/*
函数版学生管理系统
写一个系统能够查看\新增学生\删除学生
*/
var (
allStudnet map[int64]*student // 变量声明
)
type student struct {
id int64
name string
}
// newStudent 是student类型的构造函数
func newStudent(id int64, name string) *student {
return &student{
id: id,
name: name,
}
}
func showAllStudent() {
// 把所有的学生都打印出来
for k, v := range allStudnet {
fmt.Printf("学号:%d 姓名:%s\n", k, v.name)
}
}
func addStudent() {
// 向allStudent中添加一个新的学生
// 1. 创建一个新学生
// 1.1 获取用户输入
var (
id int64
name string
)
fmt.Print("请输入学生学号:")
fmt.Scanln(&id)
fmt.Print("请输入学生姓名:")
fmt.Scanln(&name)
// 1.2 造学生(调用student的构造函数)
newStu := newStudent(id, name)
// 2. 追加到allStudent这个map中
allStudnet[id] = newStu
}
func deleteStudnet() {
// 1. 请用户输入要删除的学生的序号
var (
deleteID int64
)
fmt.Print("请输入学生学号:")
fmt.Scanln(&deleteID)
// 2. 去allStudent这个map中根据学号删除对应的键值对
delete(allStudnet, deleteID)
}
func main() {
allStudnet = make(map[int64]*student, 48) // 初始化(开辟内存空间)
for {
// 1. 打印菜单
fmt.Println("欢迎光临学生管理系统!")
fmt.Println(`
1. 查看所有学生
2. 新增学生
3. 删除学生
4. 退出
`)
fmt.Print("请输入你要干啥:")
// 2. 等待用户选择要做什么
var choice int
fmt.Scanln(&choice)
fmt.Printf("你选择了%d这个选项!\n", choice)
// 3. 执行对应的函数
switch choice {
case 1:
showAllStudent()
case 2:
addStudent()
case 3:
deleteStudnet()
case 4:
os.Exit(1) // 退出
default:
fmt.Println("滚~")
}
}
}

12、#

// 匿名字段
// 字段比较少也比较简单的场景
// 不常用!!!
type person struct {
string
int
}
func main() {
p1 := person{
"周林",
9000,
}
fmt.Println(p1)
fmt.Println(p1.string)
fmt.Println(p1.int)
}

13、#

// 结构体嵌套
type address struct {
province string
city string
}
type workPlace struct {
province string
city string
}
type person struct {
name string
age int
address // 匿名嵌套结构体
workPlace
// address:address
}
type company struct {
name string
address
}
func main() {
p1 := person{
name: "周林",
age: 9000,
address: address{
province: "山东",
city: "威海",
},
}
fmt.Println(p1)
fmt.Println(p1.name, p1.address.city)
// fmt.Println(p1.city) // 先在自己结构体找这个字段,找不到就去匿名嵌套的结构体中查找该字段
fmt.Println(p1.address.city)
fmt.Println(p1.workPlace.city)
}

14、结构体模拟实现其他语言中的”继承”#

// 结构体模拟实现其他语言中的"继承"
type animal struct {
name string
}
// 给animal实现一个移动的方法
func (a animal) move() {
fmt.Printf("%s会动!\n", a.name)
}
// 狗类
type dog struct {
feet uint8
animal // animal拥有的方法,dog此时也有了【www.hlwnjl.com(互联网农家乐)下载免费程序员教程】
}
// 给dog实现一个汪汪汪的方法
func (d dog) wang() {
fmt.Printf("%s在叫:汪汪汪~\n", d.name)
}
func main() {
d1 := dog{
animal: animal{name: "周林"},
feet: 4,
}
fmt.Println(d1)
d1.wang()
d1.move() // ?
}

15、 结构体与json#

import (
"encoding/json"
"fmt"
)
// 结构体与json
// 1.序列化: 把Go语言中的结构体变量 --> json格式的字符串
// 2.反序列化: json格式的字符串 --> Go语言中能够识别的结构体变量
type person struct {
Name string `json:"name" db:"name" ini:"name"`
Age int `json:"age"`
}
func main() {
p1 := person{
Name: "周林",
Age: 9000,
}
// 序列化
b, err := json.Marshal(p1)
if err != nil {
fmt.Printf("marshal failed, err:%v", err)
return
}
fmt.Printf("%v\n", string(b))
// 反序列化
str := `{"name":"理想","age":18}`
var p2 person
json.Unmarshal([]byte(str), &p2) // 传指针是为了能在json.Unmarshal内部修改p2的值
fmt.Printf("%#v\n", p2)
}

16、#

17、#

base04-递归+结构体
https://blog.zhequtao.com/posts/golang/go-new/base/base04/
作者
阿俊
发布于
2020-03-30
许可协议
CC BY-NC-SA 4.0

相关阅读