惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
A
About on SuperTechFans
IT之家
IT之家
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Blog — PlanetScale
Blog — PlanetScale
aimingoo的专栏
aimingoo的专栏
云风的 BLOG
云风的 BLOG
The GitHub Blog
The GitHub Blog
Vercel News
Vercel News
G
Google Developers Blog
J
Java Code Geeks
宝玉的分享
宝玉的分享
T
Tailwind CSS Blog
Cloudbric
Cloudbric
L
LINUX DO - 最新话题
MyScale Blog
MyScale Blog
H
Heimdal Security Blog
PCI Perspectives
PCI Perspectives
Attack and Defense Labs
Attack and Defense Labs
S
Security @ Cisco Blogs
Latest news
Latest news
I
Intezer
L
Lohrmann on Cybersecurity
C
CXSECURITY Database RSS Feed - CXSecurity.com
月光博客
月光博客
T
Threatpost
博客园 - 【当耐特】
S
Schneier on Security
P
Privacy International News Feed
G
GRAHAM CLULEY
T
Tenable Blog
AWS News Blog
AWS News Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
雷峰网
雷峰网
博客园 - Franky
Engineering at Meta
Engineering at Meta
美团技术团队
S
Secure Thoughts
T
Troy Hunt's Blog
Microsoft Security Blog
Microsoft Security Blog
SecWiki News
SecWiki News
V
Visual Studio Blog
人人都是产品经理
人人都是产品经理
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Cisco Talos Blog
Cisco Talos Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Martin Fowler
Martin Fowler
Webroot Blog
Webroot Blog
Google DeepMind News
Google DeepMind News
H
Hackread – Cybersecurity News, Data Breaches, AI and More

博客园 - dribs

PD分离 基于GPT2训练构建医疗问诊机器人 物流行业信息咨询智能问答系统 day8 golang-chan-协程-定时器-锁-等待组 day7 golang GMP golang面试题单向链表和双向链表 golang 自行实现一个base64加密 golang标准库log+第三方zerolog golang标准库序列化反序列化 json + 第三方msgpack golang 标准库 目录操作 golang-day1 进制 golang-标准库文件操作 golang-标准库时间time day6 golang-标准库(随时更新) golang-day4函数 ceph warn oldest client/flush tid ceph 扩容后healt-error k8s系列---pod手动驱逐 k8s系列---Chart(下)
golang--day5结构体+结构体排序+错误处理+结构体和接口实现面向对象的例子
dribs · 2023-02-19 · via 博客园 - dribs

2023-02-19 10:46  dribs  阅读(45)  评论()    收藏  举报

package main

import (
	"fmt"
)

//初始化
type User struct {
	id         int
	name, addr string
	float32    //匿名成员变量 必须类型不一样才能区分
}
type Point struct {
	x, y int
}

//成员方法
//u 称为receiver
//等价于func (User)string
func (u User) getName() string {
	return u.name
}
func (p *Point) setY(v int) {
	fmt.Printf("p9set:%+v,%p\n", p, p)
	p.y = v
}
func (p Point) getY() int {
	return p.y
}

//构造函数 go本身没有为结构体提供构造器
//但是有时候可以通过一个函数为结构体初始化提供属性值
//从而方便得到一个结构体实例,习惯以Newxxx的形式命名
type Animal struct {
	name string
	age  int
}

func NewAnimal(name string, age int) *Animal {
	//a := Animal{name, age}
	//fmt.Printf("%+v,%p\n", a, &a)
	//return &a
	return &Animal{name, age} //习惯上返回值采用指针类型避免实例的拷贝
}

func main() {
	//1 var声明 非常常用
	var u1 User //这种方式声明结构体变量很方便,所有字段都是零值
	fmt.Println(u1)
	fmt.Printf("%+v\n", u1) //加上字段打印
	fmt.Printf("%#v\n", u1) //打印更多信息
	//2 字面初始化 推荐
	u2 := User{} //字段为零值
	fmt.Printf("u2:%#v\n", u2)
	//3 字面量初始化 field:value 为字段赋值
	u3 := User{id: 100}
	fmt.Printf("u3:%+v\n", u3)
	//访问
	fmt.Println(u3.id)
	//修改
	u3.id = 200
	u3.name = "Tom"
	fmt.Println(u3)
	//通过成员方法访问
	fmt.Println(u3.getName())

	//指针
	var p1 = Point{10, 20} //实例
	fmt.Printf("p1:%T,%[1]v\n", p1)
	var p2 = &Point{5, 6} //指针
	fmt.Printf("p2:%T,%[1]v\n", p2)
	var p3 = new(Point) //new实例化一个结构体并返回
	fmt.Printf("p3:%T,%[1]v\n", p3)
	//通过实例修改属性
	p1.x = 100
	fmt.Printf("%T,%[1]v\n", p1)

	p4 := p1 //多了一个副本,内存地址不一样
	fmt.Printf("p1:%+v %p\n", p1, &p1)
	fmt.Printf("p4:%+v %p\n", p4, &p4)
	p5 := &p1 //p5 就是p1的引用了 传递的是一个地址
	fmt.Printf("p5:%+v %p\n", p5, p5)
	var p6 = func(p Point) Point {
		fmt.Printf("p6inner:%+v,%p\n", p, &p)
		return p
	}(p1)
	fmt.Printf("p6outer:%+v,%p\n", p6, &p6)
	//可以看出 结构体是非引用类型 使用的是值拷贝,传参活返回值如果使用结构体实例,将产生很多副本
	//如何避免多副本,保证函数内外是同一个结构体实例,使用指针
	var p7 = func(p *Point) *Point {
		p.x += 200
		fmt.Printf("p7inner:%+v,%p\n", p, p)
		return p
	}(p5)
	p7.x += 1
	fmt.Printf("p1:%+v %p\n", p1, &p1)
	fmt.Printf("p7outer: %+v,%p\n", p7, &p7)
	p8 := p5
	p8.y = 400 //会发生什么??
	fmt.Printf("p1:%+v %p\n", p1, &p1)
	fmt.Printf("p8: %+v,%p\n", p8, p8)

	//匿名结构体,标识符直接使用struct部分结构体本身作为类型,而不是使用type定义的有名字的结构体的标识符
	//可以使用 var const := 来定义匿名结构体,结构体可以反复定义其实例,但匿名的是一次性的
	var point struct {
		x, y int
	}
	fmt.Printf("匿名结构体:%v\n", point) //得到的是一个结构体的实例,默认是零值
	var message = struct {
		id   int
		data string
	}{1, "abc"} //不用零值初始化 注意有个=
	fmt.Printf("%v\n", message)
	//匿名成员
	var u4 = User{id: 10, name: "Bob", float32: 1.111} //使用类型名float最为字段名
	fmt.Println(u4, u4.float32)

	//构造函数
	a := NewAnimal("Tom", 18)
	fmt.Printf("构造函数:%+v,%p\n", a, a) //返回的指针和构造函数里一样

	//指针类型recevier
	p9 := Point{66, 88}
	fmt.Printf("p9:%+v,%p\n", p9, &p9)
	p9.setY(201) //看似是Point{66, 88}实例调用,因为func (p *Point) setY 所以实际是指针,操作同一处地址
	fmt.Println(p9.getY())
}

对切片排序和利用结构体对map排序  

package main

import (
	"fmt"
	"sort"
)

type Student struct {
	Name string
	Age  int
}

//用于对map的value排序使用,map的格式很像struct格式
type Entry struct {
	key   int
	value string
}

type StudentSlice []Student

func (x StudentSlice) Len() int {
	return len(x)
}
func (x StudentSlice) Swap(i, j int) {
	x[i], x[j] = x[j], x[i]
}
func (x StudentSlice) Less(i, j int) bool {
	return x[i].Age > x[j].Age
}
func main() {
	students := make([]Student, 0, 3)
	students = append(students, Student{"Tom", 19})
	students = append(students, Student{"Jack", 18})
	students = append(students, Student{"Rose", 20})
	fmt.Println(students)
	sort.Sort(StudentSlice(students))
	fmt.Println(students)

	//简化版13-23行的代码可以去掉,直接匿名函数实现Less
	sort.Slice(students, func(i, j int) bool {
		return students[i].Age < students[i].Age
	})
	fmt.Println(students)

	//对map排序之对map的key排序,先取出key,放到int[]切片里,然后对int[]切片排序,在根据排序好的切片 获取map对应的value
	m := make(map[int]string)
	m[1] = "b"
	m[2] = "c"
	m[0] = "a"
	var keys []int
	for k := range m {
		keys = append(keys, k)
	}
	sort.Ints(keys)
	for _, v := range keys {
		fmt.Println(v, m[v])
	}

	//对map排序之对map的value排序
	//创建一个Entry类型的切片,存放字典里的k,v
	p := make([]Entry, len(m))
	i := 0
	//
	for k, v := range m {
		p[i] = Entry{k, v}
		i++
	}
	fmt.Println(p)
	sort.Slice(p, func(i, j int) bool {
		return p[i].value > p[j].value
	})
	fmt.Println(p)
}
package main

import (
	"errors"
	"fmt"
	"io/fs"
	"os"
)

//panic执行:
//逆序执行当前已经注册过的goroutine的defer链(recover从这里介入)
//打印错误信息和调用堆栈
//调用exit(2)结束整个进程
//recover 类似python的 try catch 捕获异常

var ErrdivisionByZero = errors.New("division by zero") //构造一个错误实例

func div(a, b int) int {
	defer func() {
		err := recover() //一旦recover了,就相当处理过了错误
		println(1, err, "====")
	}()
	defer fmt.Println("start")
	defer fmt.Println(a, b)
	defer func() {
		println("错误捕获")
		err := recover()
		switch err.(type) { //类型断言
		case *fs.PathError:
			println("文件不存在", err)
		case []int:
			println("切片", err)
		}
		println("离开")
	}()
	if f, err := os.Open("o:/tttt.txt"); err != nil {
		panic(err)
	} else {
		println(f)
	}
	r := a / b
	println("end")
	return r
}

func main() {
	println(div(5, 0))
}

1.计算三角形长方形圆形的面积

2.计算完的面积排序处理

package main

import (
	"fmt"
	"sort"
)

//定义Area接口 用于多态实现
type Areaer interface {
	area() int
}

//圆形
type Yuan struct {
	pi float32
	r  int
}

//长方形
type Chang struct {
	w, l int
}

//三角形
type San struct {
	Chang //匿名嵌套长方形,实现继承的效果
}

//第二题构建三个以上图形排序的结构体
type AllGraph struct {
	name string
	area int
}

//第二题使用,构造函数
func NewAllGraph(name string, area int) *AllGraph {
	return &AllGraph{name, area}
}

//第二题使用排序
type AllgraphSlice []AllGraph

func (x AllgraphSlice) Len() int      { return len(x) }
func (x AllgraphSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x AllgraphSlice) Less(i, j int) bool {
	//降序排序
	return x[i].area > x[j].area

}

//实现多态
func foo(a Areaer) int {
	//a.area()
	return a.area()
}

//求三种类型的面积*(圆 长方形 三角形)
func (y *Yuan) area() int {
	area := y.pi * float32(y.r*y.r)
	//fmt.Printf("圆形面积是:%.f\n", area)
	return int(area)
}
func (c *Chang) area() int {
	area := c.w * c.l
	//fmt.Printf("长方形面积是:%d\n", area)
	return area
}
func (s *San) area() int {
	area := s.w * s.l / 2
	//fmt.Printf("三角形面积是:%d\n", area)
	return area
}

func main() {
	//第一题求面积
	//圆形面积 pi*r^2
	y1 := &Yuan{3.14, 3}
	//y1.area()
	fmt.Printf("圆形面积是:%d\n", y1.area())

	//长方形面积 长*宽
	c1 := new(Chang)
	c1.w = 3
	c1.l = 4
	//c1.area()
	fmt.Printf("长方形面积是:%d\n", c1.area())

	//三角形面积 底*高/2 ,三角形继承长方形,多态实现求面积
	s1 := &San{}
	s1.w = 10
	s1.Chang.l = 4
	//foo(s1)
	fmt.Printf("三角形面积是:%d\n", foo(s1))

	//+++++++++++++++++++++++++++++++++++++++++++++++++
	//第二题对面积排序 使用切片方式排序
	//构建三个实例,构建成map也适用
	n1 := NewAllGraph("Yuan", foo(y1))
	n2 := NewAllGraph("Chang", foo(c1))
	n3 := NewAllGraph("San", foo(s1))
	alls := []AllGraph{*n1, *n2, *n3}
	fmt.Println("排序前:", alls)
	//对结构体 降序排序
	sort.Sort(AllgraphSlice(alls))
	fmt.Println("排序后:", alls)
	//切片排序第二种方法 简易版
	sort.Slice(alls, func(i, j int) bool {
		//升序
		return alls[i].area < alls[j].area
	})
	fmt.Println("升排序:", alls)

	//对key string类型排序
	var keys []string
	for i := 0; i < len(alls); i++ {
		keys = append(keys, alls[i].name)
	}
	//区分验证上面的排序准确性 在单独append追加一个string,没写完还要一个map 不想写了
	keys = append(keys, "AAA")
	sort.Strings(keys)
	fmt.Println(keys)

}