go的结构体、方法、接口
结构体:
结构体:不同类型数据集合
结构体成员是由一系列的成员变量构成,这些成员变量也被称为“字段”
先声明一下我们的结构体:
type Person struct {name stringage intsex string
}
定义结构体法1:
var p1 Personfmt.Println(p1)p1.name = "XUPT"p1.sex = "无性别"p1.age = 74
定义结构体法2:
p2 := Person{}p2.age = 244p2.name = "艾美莉卡"p2.sex = "沃尔玛购物袋"fmt.Println(p2) //{艾美莉卡 244 沃尔玛购物袋}
定义结构体法3:
p3 := Person{name: "荷叶饭",sex: "女",age: 18, //加逗号}fmt.Println(p3) //{荷叶饭 18 女}
定义结构体法4:
p4 := Person{"米库",16,"女",}fmt.Println(p4) //{米库 16 女}
结构体为值类型,默认深拷贝(连同对象引用的所有嵌套对象(或指针指向的对象)都进行独立的复制),往往用指针操纵:
fmt.Printf("%T\n", &p4) //*main.Personfmt.Printf("%T\n", p1) //main.Person
当你对一个结构体变量取地址时,返回的是这个结构体在内存中的存储位置,这个“储存位置”就是用指针类型来储存的
定义结构体指针:
var pp1 *Personpp1 = &p1//p1是一个结构体,对p1取地址就是一个指针,所以可以画等号fmt.Println(pp1)fmt.Printf("%p,%T\n", pp1, pp1) //0xc0001040c0,*main.Personfmt.Println(*pp1) //{XUPT 74 无性别}
使用内置函数new(),go中专门用来创建某种类型的指针的函数
pp2 := new(Person)fmt.Printf("%p,%T\n", pp2, pp2) //0xc0000202d0,*main.Person,指针类型(*pp2).name = "zyzy"//也可以省略前面的*号,pp2.name="tzz"(*pp2).age = 22(*pp2).sex = "男"fmt.Println(pp2) //&{zyzy 22 男}
创建匿名结构体,一个没有名称的结构体:
s2 := struct {name stringage int}{name: "无敌高考大王",age: 18,}fmt.Println(s2.name, s2.age)
好处:
简洁性
- 代码简洁:匿名结构体允许我们在定义变量的同时声明其类型,这减少了代码量并提高了可读性。
- 减少命名负担:对于只使用一次的小型结构体,无需费心命名。
- 即时定义:在函数或方法中快速定义新的数据结构,非常适合处理一次性的、结构简单的数据。
结构体允许其成员字段在声明时没有字段名而只有类型,这种没有名字的字段就称为匿名字段。
type Worker struct {/*name stringage int*/stringint //匿名字段
}
定义一个含匿名字段的结构体:
w2 := Worker{"无敌崩坏星穹铁道大王",18,}fmt.Println(w2.string, w2.int) //打印匿名字段结构体
嵌套结构体:
结构体里套着结构体:
type Book struct {bookName stringprice float64
}
type Studentbook struct {name stringage intbook Book
}
定义法1:
ss2 := Studentbook{name: "code",age: 18,book: Book{"西西弗神话",24.9,},}fmt.Println(ss2)
定义法2:
bb1 := Book{}bb1.bookName = "1984"bb1.price = 45.8ss1 := Studentbook{}ss1.name = "奥威尔"ss1.age = 24ss1.book = bb1fmt.Println(bb1)fmt.Println(ss1)
定义法3:
bb3 := Book{bookName: "三体",price: 14.9,}ss3 := Studentbook2{name: "刘慈欣",age: 18,book: &bb3,}fmt.Println(bb3) //{三体 14.9}fmt.Println(ss3)
type关键字
1.类型定义:type 类型名 Type
2.类型别名:type 类型名=Type
var i1 myint //intvar i2 = 100 //intvar str1 mystrstr1 = "嘻嘻"
//main函数外
type myint int
type mystr string
看上去好像myint和int没什么区别?
打印一下他们的数据类型:
fmt.Printf("i1类型==%T\ni2类型==%T\n", i1, i2)//i2!=i1,i1,i2是两种语法类型
fmt.Printf("str1类型==%T\n", str1) //main.mystr
所以他们不是同一种数据类型,不能直接相等哦
我们也可以用type来重命名我们的函数类型:
type myfun func(int, int) string//定义一个新的函数类型,myfun就等价于 func(int,int)string
//照这个类型定义一个函数,等价于 func fun11() func(int, int) string
func fun11() myfun {fun := func(a, b int) string {s := strconv.Itoa(a) + strconv.Itoa(b)return s}return fun
}
/*
上述函数等价于
func fun11() func(int, int) string {fun := func(a, b int) string {s := strconv.Itoa(a) + strconv.Itoa(b)return s}return fun
}*/
调用我们的函数:
res1 := fun11()fmt.Println(res1(10, 20)) //拼接10和20type myint2 = int //给int起了别名,就像define
放弃了大量面向对象的特性,首字母大写可共用,小写为私用
这个类的私用和共用和保护在c++中是这么体现的:
class BaseClass {
public:// 公有成员int publicData;protected:// 保护成员int protectedData;
};class DerivedClass : public BaseClass {
public:// 在派生类中可以访问基类的保护成员void accessProtected() {protectedData = 42; // 正常访问}private:// 派生类有自己的私有成员int derivedPrivate;
};int main() {DerivedClass d;d.publicData = 10; // 可见,因为是公有的d.accessProtected(); // 可见,因为DerivedClass继承了BaseClass// BaseClass的对象尝试访问protectedData是不允许的// BaseClass base;// base.protectedData = 50; // 错误,protectedData仅对DerivedClass可见return 0;
}
如果我们写成go应该是这样的:
package mainimport "fmt"type BaseClass struct {PublicData int //共有字段protectData int //protected,只能在包内私用,未导出的字段
}// 模拟c++的继承,嵌套结构体
type DerivedClass struct {BaseClassderivedPrivate int
}func (d *DerivedClass) AccessProtected() {d.protectData = 42 //访问我们未导出的protected字段fmt.Println("protectData==", d.protectData)
}
func main() {d := DerivedClass{}d.PublicData = 10fmt.Println("d.PublicData==", d.PublicData)d.AccessProtected()base := BaseClass{}base.protectData = 50 // 如果在c++里编译错误:无法访问,因为我们的protected是对于派生类可以被访问//但是在go里,我们不能把protected限定在类里,只能控制它在包内和包外是否可调用fmt.Println(base.protectData) //50fmt.Println("program finished")
}
很显然我们的go在面向对象这方面并不能像c++一样(比如我们的protected类)
oop(面向对象)
面向对象和面向过程的区别:
其实不止操作系统,很多系统的管理模式都是用面向对象的模式管理的
管理者并不在乎你每个人的个体特征。
在公司里,老板让你买咖啡,并且他很急。买咖啡有多种方式,例如点外卖、自己到楼下购买、托正在外面的同事捎来或者给老板花超绝三块钱冲雀巢等等。然后你就问老板说:老板,那我是去点外卖还是自己买还是给你冲速溶咖啡还是......老板根本不在乎你说的什么,他只会告诉你:不管怎样,我只要我的桌子上放有咖啡。
员工只要搞到咖啡就好了,而老板考虑的就多了(勾潮的鸣式还在追我
老板这个命令就叫面向对象(oop)他不在乎事情处理的过程;底层员工要做的就是处理好这些事情的过程。
面向对象就是把拥有复杂过程的事情抽象为一个类,比如在这里我们把自己买咖啡、点外卖、冲咖啡这种事情全部抽象为搞到咖啡(其实很像那些不近人情的上级会说:我不问过程只要结果呃呃)
本质上获得咖啡的途径,就是面向过程(opp)。也就是说,面向对象的最底层的实现方法还是面向过程。只不过在这里,面向过程被我们抽象为一个类。
按C++的STL来举例子:首先我们需要一个工具箱,里面装着我们需要的东西。于是我们先创造了工具箱这个东西;然后我们就要想在我们的工具箱里塞什么东西,比如说我需要一个排序的函数,需要一个求大值、最小值的函数;然后我们再去编写函数里面的内容,这个函数最里面的内容是面向过程,然后外边整体用的是面向对象的思想。
也就是说对特定对象先描述,再组织
————————————————之前写的部分
原文链接:https://blog.csdn.net/Au_ust/article/details/141108377
对象是最基本的单位,例如switch就是一个对象,描述他的有属性(是个程序员)和方法(打炉石传说)
这种类型的人可以被抽象、概括出来,就是一个类,例如上述的像switch一样的人可以被抽象为爱打炉石传说的程序员,像她一样爱打炉石传说的程序员都在这个类里面
面向对象编程具有三大特性:封装、继承、多态。
封装:将对象的属性和方法打包
继承:子类可以继承父类已有的功能
多态:不同的类执行不同的方法有不同的结果
在go语言中其实并不具有一种完备的面向对象的机制,没有什么内联函数,不如c++
但是我们可以使用偷感很重的方式:用接口和方法模拟oop的特性:
1.模拟继承性:is-a(是),一个类继承一个类
子类可以直接访问父类的属性和方法
子类可以新增自己的属性和方法
子类可以重写父类的方法(override,就是将父类已有的方法,重新实现)
type A struct{
field
}
type B struct{
A//匿名字段
//可以在B的里面,在A的基础上修改A的方法属性
}
2.模拟聚合关系 has-a(有),一个类拥有一个类
//这个很好理解
type C struct{field
}
type D struct{c C//聚合关系
}
3.模拟多态
一个对象受到类型的限制,可以定义为父类类型,也可以定义为子类,类似于界门纲目科属种的关系
类型不同,能够访问的字段(功能)不同
go语言通过接口模拟多态,就是一个接口的实现
1.看成实现本身的类型,能够访问实现类中的属性和方法
2.看成是对应接口的类型,只能访问接口中定义的方法
一个很弱智很普通的模拟面向对象的实现:
package mainimport "fmt"func main() {//1.创建父类对象p1 := Personoop{"张三", 18}fmt.Println(p1)fmt.Println(p1.name, p1.age)//2.创建子类对象s1 := Studentoop{Personoop{"李四", 18}, "XUPT"}fmt.Println(s1)s2 := Studentoop{Personoop: Personoop{"王五", 18}, school: "XUPT"}fmt.Println(s2)var s3 Studentoops3.Personoop.name = "老公"s3.Personoop.age = 18s3.school = "CCUT"fmt.Println(s3) //{{老公 18} CCUT}//Personoop在Studentoopz中为匿名结构体字段,被称为提升字段//因此可以如下命名s3.name = "荷叶饭"s3.age = 16s3.school = "我不要上学"fmt.Println(s3) //{{荷叶饭,16} 我不要上学}
}// 1.定义父类
type Personoop struct {name stringage int
}
// 2.定义子类//is-a的关系
type Studentoop struct {Personoop //结构体嵌套模拟继承结构,提升字段,可以直接进行访问school string //子类的新增属性
}
差不多就是这个意思,等下讲接口
方法(method)
方法的本质是一种函数,但是是定义了接受者的函数,这个接受者可以是很多种数据类型,还要结构体类型中的值或指针
所有给定统一类型的方法称为该类型的方法集。比如虾头太刀侠,可以登!龙!,还可以进行气刃大回旋,登龙和气刃大回旋就是虾头太刀侠的方法集
方法的名字可以重复,但是method区别调用者
语法:func(接受者)方法名(参数列表)(返回值列表){}
来写一个样例看看:
type Worker1 struct {name stringage intsex string
}//结构体定义部分
func (w Worker1) work() {fmt.Println(w.name, "在工作")
}//工作方法
func (p *Worker1) rest() {fmt.Println(p.name, "在休息")
}//休息方法func main(){w1 := Worker1{name: "张三", age: 18, sex: "男"}w1.work() //张三 在工作w2 := &Worker1{name: "李四", age: 18, sex: "女"}w2.rest() //李四 在休息}
方法可以重名,我们创建一个新的类和刚刚的类对比:
type Worker1 struct {name stringage intsex string
}
type Cat struct {name stringcolor stringsex string
}func (p *Worker1) printfInfo() {fmt.Println("name:", p.name, "age:", p.age, "sex", p.sex)
}
func (p *Cat) printfInfo() {fmt.Println("name:", p.name, "color:", p.color, "sex:", p.sex)
}func main(){w1 := Worker1{name: "张三", age: 18, sex: "男"}c1 := Cat{name: "艾露猫", color: "浅棕色", sex: "男"}c1.printfInfo() //name: 艾露猫 color: 浅棕色 sex: 男c1.name = "呆猫"c1.printfInfo() //name: 呆猫 color: 浅棕色 sex: 男w1.printfInfo() //name: 张三 age: 18 sex 男//方法可以重名,因为接受者不同}
新增方法和重写方法的区别:
func main(){//创建Personmethod类型p1 := Personmethod{"王二狗", 18}fmt.Println(p1) //{王二狗 18}p1.eat() //父类的方法,吃盖浇面s1 := Studentmethod{Personmethod{"ruby", 18}, "XUPT"}fmt.Println(s1) //{{ruby 18} XUPT}s1.study() //子类的新增方法,学生学习s1.eat() //子类重写的方法,吃炸鸡}
// 继承中的方法
// 定义一个“父类”
type Personmethod struct {name stringage int
}// 定义一个子类
type Studentmethod struct {Personmethodschool string
}// 定义一个父类方法
func (p Personmethod) eat() {fmt.Println("父类的方法,吃盖浇面")
}// 定义一个子类方法
func (p Studentmethod) study() {fmt.Println("子类的新增方法,学生学习")//和子类的类型一样,方法名不一样
}
func (p Studentmethod) eat() {fmt.Println("子类重写的方法,吃炸鸡")//重写是名字一样,类型不一样
}
接口(interface)
接口是对方法的抽象,例如:你会吃东西,说明你肯定是个生物,但是如果你又会吃东西,还会玩元神,那你就是个私宅;所以吃东西可以单独做一个接口,吃东西和玩元神也可以做另一个接口
这样叫通过方法来确定你的类型(鸭子类型)
go语言中,接口类型的实现关系,是非侵入式:只实现,不用在乎是谁实现的
java中要显示定义
eg:
class Mouse implements USB{}
package main
import ("fmt"
)
func main(){//1.创建mouse类型m1 := Mouse{"罗技小红"}fmt.Println(m1)//2.创建FlashDiskf1 := FlashDisk{"闪速64G"}fmt.Println(f1)testIterface(m1)//鼠标就会从testIterface中的USB中找到鼠标对应的start方法testIterface(f1)//同上}
func testIterface(usb USB) { //usb=m1 usb=f1usb.start()usb.end()
}//测试我们接口的函数type USB interface {start()end()
}//USB接口
func (m Mouse) start() {fmt.Println("Mouse.start")
}
func (m Mouse) end() {fmt.Println("Mouse.end")
}//对应的鼠标方法
func (f FlashDisk) start() {fmt.Println("FlashDisk.start")
}
func (f FlashDisk) end() {fmt.Println("FlashDisk.end")
}//对应的FlashDisk方法
也可以把main函数里面写成这样:
var usb USBusb = m1usb.start()usb.end()usb = f1usb.start()usb.end()
可以更明显的看出接口对同类的不同对象方法的抽象
空接口
没有任何方法签名的接口叫空接口
写一个空接口:
package main
import ("fmt"
)
func main() {var a1 A = Dog{"黑犬"}var a2 A = People{"纸包鱼", 30}fmt.Println(a1, a2) //{黑犬} {纸包鱼 30}test1(a1) //{黑犬}test1(a2) //{纸包鱼 30}test2(a1) //空接口 {黑犬}test2(a2) //空接口 {纸包鱼 30}//空接口代表任意类型的使用slice1 := make([]interface{}, 0, 10)slice1 = append(slice1, a1, a2, 100, "abc") //[{黑犬} {纸包鱼 30} 100 abc]fmt.Println(slice1)
}func test1(a A) {fmt.Println(a)
}
func test2(a interface{}) {fmt.Println("空接口", a)
}// 空接口
type A interface {
}
空接口中不限制数据类型
接口嵌套,可以模拟oop的继承特性,也可以通过不同接口看是什么接口类型,可以把实现类型看成接口类型:
package main
import ("fmt"
)
func main() {var dog Dog = Dog{"青色"}dog.test11()dog.test22()dog.test33()fmt.Println("------分隔符------")var aa1 AA = dog //AA接口类型aa1.test11()fmt.Println("------分隔符------")var bb1 BB = dog //BB接口类型bb1.test22()fmt.Println("------分隔符------")var cc1 CC = dog //CC接口类型cc1.test11()cc1.test22()cc1.test33()
}
type AA interface {test11()
}
type BB interface {test22()
}
type CC interface {AABBtest33()
}func (d Dog) test11() {fmt.Println("test11...")
}
func (d Dog) test22() {fmt.Println("test22...")
} //如果test11和test22都能实现,则Dog同时是AA和BB的实现
func (d Dog) test33() {fmt.Println("test33...")
}
接口断言
我们可以通过接口来判断实现类型。那么如果是空接口呢?或者两个类都可以实现同一个接口下的方法呢?比如你会翻滚,烤肠机上的烤肠也会翻滚,那么如何区分你和烤肠呢?
package mainimport ("fmt""math"
)func main() {var t1 Triangle = Triangle{3, 4, 5}fmt.Println(t1.perimeter()) //12fmt.Println(t1.area()) //6var c1 Circle = Circle{5}fmt.Println(c1.perimeter()) //31.41592653589793fmt.Println(c1.area()) //78.53981633974483var s1 Shape //Shape类型,但是没有确定为Triangle类型还是Circle类型s1 = t1 //定义为Triangle类型fmt.Println(s1.perimeter())fmt.Println(s1.area())//fmt.Println(s1.a,s1.b,s1.c),打印不了,因为s1是Shape接口类型testShape(t1) //周长 12 面积 6testShape(c1) //周长 31.41592653589793 面积 78.53981633974483getType(t1) //是三角形,三边为 3 4 5getType(c1) //是圆形半径为 5getType(s1) //是三角形,三边为 3 4 5var t2 *Triangle = &Triangle{3, 4, 5}getType(t2) //ins:*main.Triangle 0xc000058030//s:*main.Triangle 0xc0000260a0,地址不一样,值传递getType1(t2) //三角形结构体指针 3 4 5
}
func getType(s Shape) {//断言,判断接口对象是不是对应的实际类型//1.if分支if ins, ok := s.(Triangle); ok {fmt.Println("是三角形,三边为", ins.a, ins.b, ins.c)} else if ins, ok := s.(Circle); ok {fmt.Println("是圆形半径为", ins.radius)} else if ins, ok := s.(*Triangle); ok {fmt.Printf("ins:%T %p\n", ins, &ins)fmt.Printf("s:%T %p\n", s, &s)} else {fmt.Println("我也不知道")}
}
func getType1(s Shape) {//2.switch分支switch ins := s.(type) {case Triangle:fmt.Println("是三角形,三边为", ins.a, ins.b, ins.c)case Circle:fmt.Println("是圆形半径为", ins.radius)case *Triangle:fmt.Println("三角形结构体指针", ins.a, ins.b, ins.c)}
}
func testShape(s Shape) {fmt.Println("周长", s.perimeter(), "面积", s.area())
}// 1.定义一个接口
type Shape interface {perimeter() float64area() float64
}// 2.定义实现类
type Triangle struct {a, b, c float64
}func (t Triangle) perimeter() float64 {return t.a + t.b + t.c
}
func (t Triangle) area() float64 {p := t.perimeter() / 2s := math.Sqrt(p * (p - t.a) * (p - t.b) * (p - t.c))return s
}type Circle struct {radius float64
}func (c Circle) perimeter() float64 {return math.Pi * c.radius * 2
}
func (c Circle) area() float64 {return math.Pi * c.radius * c.radius
}
相关文章:

go的结构体、方法、接口
结构体: 结构体:不同类型数据集合 结构体成员是由一系列的成员变量构成,这些成员变量也被称为“字段” 先声明一下我们的结构体: type Person struct {name stringage intsex string } 定义结构体法1: var p1 P…...
力扣第一题——删除有序数组中的重复项
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次,返回删除后数组的新长度。不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1)额外空间的条件下完成。 示例 1&#x…...

Tuxera NTFS for Mac 2023绿色版
在数字化时代,数据的存储和传输变得至关重要。Mac用户经常需要在Windows NTFS格式的移动硬盘上进行读写操作,然而,由于MacOS系统默认不支持NTFS的写操作,这就需要我们寻找一款高效的读写软件。Tuxera NTFS for Mac 2023便是其中…...

LeetCode[中等] 155. 最小栈
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void pop() 删除堆栈顶部的元素。int top() 获取堆栈顶部的元素。int get…...
Python青少年简明教程目录
Python青少年简明教程目录 学习编程语言时,会遇到“开头难”和“深入难”的问题,这是许多编程学习者都会经历的普遍现象。 学习Python对于青少年来说是一个很好的编程起点,相对容易上手入门,但语言特性复杂,应用较广&…...
Revit学习记录-版本2018【持续补充】
将墙面拆分并使用不同材料 【修改】>【几何图形】>【拆分面】(SF), 然后再使用【修改】>【几何图形】>【填色】(PT)进行填充 楼板漏在墙外 绘制楼板时最好选择墙体绘制,如果标高上不显示墙体,可以先选…...

深度学习01-概述
深度学习是机器学习的一个子集。机器学习是实现人工智能的一种途径,而深度学习则是通过多层神经网络模拟人类大脑的方式进行学习和知识提取。 深度学习的关键特点: 1. 自动提取特征:与传统的机器学习方法不同,深度学习不需要手动…...

leetcode232. 用栈实现队列
leetcode232. 用栈实现队列 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty): 实现 MyQueue 类: void push(int x) 将元素 x 推到队列的末尾 int pop() 从队列的开头移除并返回元…...

智慧火灾应急救援航拍检测数据集(无人机视角)
智慧火灾应急救援。 无人机,直升机等航拍视角下火灾应急救援检测数据集,数据分别标注了火,人,车辆这三个要素内容,29810张高清航拍影像,共31GB,适合森林防火,应急救援等方向的学术研…...

eureka.client.service-url.defaultZone的坑
错误的配置 eureka: client: service-url: default-zone: http://192.168.100.10:8080/eureka正确的配置 eureka: client: service-url: defaultZone: http://192.168.100.10:8080/eureka根据错误日志堆栈打断电调试 出现两个key,也就是defaultZone不支持snake-c…...

统信服务器操作系统【d版字符系统升级到dde图形化】配置方法
统信服务器操作系统d版本上由字符系统升级到 dde 桌面系统的过程 文章目录 一、准备环境二、功能描述安装步骤1. lightdm 安装2. dde 安装 一、准备环境 适用版本:■UOS服务器操作系统d版 适用架构:■ARM64、AMD64、MIPS64 网络:连接互联网…...

学习IEC 62055付费系统标准
1.IEC 62055 国际标准 IEC 62055 是目前关于付费系统的唯一国际标准,涵盖了付费系统、CIS 用户信息系统、售电系统、传输介质、数据传输标准、预付费电能表以及接口标准等内容。 IEC 62055-21 标准化架构IEC 62055-31 1 级和 2 级有功预付费电能表IEC 62055-41 STS…...

如何在Markdown写文章上传到wordpress保证图片不丢失
如何在Markdown写文章上传到wordpress保证图片不丢失 写文日期,2023-11-16 引文 众所周知markdown是一款nb的笔记软件,本篇文章讲解如何在markdown编写文件后上传至wordpress论坛。并且保证图片不丢失(将图片上传至云端而非本地方法) 一&…...

html,css基础知识点笔记(二)
9.18(二) 本文主要教列表的样式设计 1)文本溢出 效果图 文字限制一行显示几个字,多余打点 line-height: 1.8em; white-space: nowrap; width: 40em; overflow: hidden; text-overflow: ellipsis;em表示一个文字的大小单位&…...
(k8s)kubernetes 部署Promehteus学习之路
整个Prometheus生态包含多个组件,除了Prometheus server组件其余都是可选的 Prometheus Server:主要的核心组件,用来收集和存储时间序列数据。 Client Library::客户端库,为需要监控的服务生成相应的 metrics 并暴露给…...

初写MySQL四张表:(3/4)
我们已经完成了四张表的创建,学会了创建表和查看表字段信息的语句。 初写MySQL四张表:(1/4)-CSDN博客 初写MySQL四张表:(2/4)-CSDN博客 接下来,我们来学点对数据的操作:增 删 查(一部分)改 先来看这四张表以及相关…...

【Java】线程暂停比拼:wait() 和 sleep()的较量
欢迎浏览高耳机的博客 希望我们彼此都有更好的收获 感谢三连支持! 在Java多线程编程中,合理地控制线程的执行是至关重要的。wait()和sleep()是两个常用的方法,它们都可以用来暂停线程的执行,但它们之间存在着显著的差异。本文将详…...

CQRS模型解析
简介 CQRS中文意思为命令于查询职责分离,我们可以将其了解成读写分离的思想。分为两个部分 业务侧和数据侧,业务侧主要执行的就是数据的写操作,而数据侧主要执行的就是数据的读操作。当然两侧的数据库可以是不同的。目前最为常用的CQRS思想方…...

qt-C++笔记之作用等同的宏和关键字
qt-C笔记之作用等同的宏和关键字 code review! Q_SLOT 和 slots: Q_SLOT是slots的替代宏,用于声明槽函数。 Q_SIGNAL 和 signals: Q_SIGNAL类似于signals,用于声明信号。 Q_EMIT 和 emit: Q_EMIT 是 Qt 中用于发射…...

java(3)数组的定义与使用
目录 1.前言 2.正文 2.1数组的概念 2.2数组的创建与初始化 2.2.1数组的创建 2.2.1数组的静态初始化 2.2.2数组的动态初始化 2.3数组是引用类型 2.3.1引用类型与基本类型区别 2.3.2认识NULL 2.4二维数组 2.5数组的基本运用 2.5.1数组的遍历 2.5.2数组转字符串 2.…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...