go学习之接口知识

news2024/11/18 9:42:01

文章目录

    • 接口
      • 1.接口案例代码展示
      • 2.基本介绍
      • 3.基本语法
      • 4.应用场景介绍
      • 5.注意事项和细节
      • 6.接口编程经典案例
      • 7.接口与继承之间的比较
      • 8.面向对象编程--多态
        • 1)基本介绍
        • 2)快速入门
        • 3)接口体现多态的两种形式
      • 9.类型断言
        • 1)先看一个需求
        • 2)基本介绍
        • 3)类型断言的最佳实践1
        • 4)类型断言实践2

接口

1.接口案例代码展示

模拟通过支持usb接口的手机和相机开始工作

package main
import (
	"fmt"
)

//声明定义一个接口
type Usb interface{
	Start()
	Stop()
}

type Phone struct {

}

type Camera struct {

}
//让phone实现usb接口的方法
func (p Phone) Start(){
	fmt.Println("手机开始工作。。。")
}
func (p Phone) Stop(){
	fmt.Println("手机停止工作。。。")
}

func (c Camera) Start(){
	fmt.Println("相机开始工作。。。")
}
func (c Camera) Stop(){
	fmt.Println("相机停止工作。。。")
}
//计算机
type Computer struct{

}

//编写一个方法Working方法,接收一个Usb接口类型变量
//只要是实现了Usb接口(所谓实现Usb接口,就是指实现了Usb接口声明所有方法)
func (c Computer) Working (usb Usb){
	//通过usb接口变量来调用Start和Stop方法
     usb.Start()
	 usb.Stop()
}
func main(){

	//测试
	//先创建结构体变量
	computer :=Computer{}
	phone :=Phone{}
	camera := Camera{}

	//关键点
	computer.Working(phone)
	computer.Working(camera)


}

2.基本介绍

interface类型可以定义一组方法,但是这些不需要实现。并且interface不能包含任何变量,到某个自定义类型(比如结构体Phone)要使用的时候,再根据具体情况把这些方法写出来

3.基本语法

type 接口名 interface{
  method1(参数列表)返回值列表
  method2(参数列表)返回值列表
}

实现接口的方法
func (t 自定义类型)method1(参数列表)返回值列表{
 //方法实现
}
func (t 自定义类型)method2(参数列表)返回值列表{
 //方法实现
}

小结说明:

1)接口里的所有方法都没有方法体,即接口的方法都是没有实现的方法。接口体现了程序设计的多态和高内聚低耦合的思想。

2)Golang中的接口,不需要显式的实现。只要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口。因此,Golang中没有implement这样的关键字

解释:假如有一个不同名字的接口,但是方法和原接口的方法一样,那么实现的方法也是实现了这个接口,golang中接口的实现不是基于名字而是基于方法。可以同时实现两个接口。

type Usb interface{
    Start()
	Stop()
}
type Usb2 interface{
	Start()
	Stop()
}

4.应用场景介绍

对初学者讲,理解接口不算太难,难的是不知道什么时候使用接口,下面几个例子来解释

1)现在美国要制造轰炸机,武装直升机,专家只需要把飞机需要的功能/规格定下来即可,然后让别人具体实现即可

2)就是做一个项目,在接口中定义规范让其他人去实现所定的规范

5.注意事项和细节

1)接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量(实例)

package main
import (
	"fmt"
)

type AInterface interface {
	Say()

}

type Stu struct {
	Name string
}
func (stu Stu)Say(){
	fmt.Println("Stu Say()")
}
func main(){
   var stu Stu  //结构体变量,实现了Say() 实现了AInterface这个接口
   var a AInterface =stu
   a.Say() //Stu Say()
}

2)接口中所有的方法都没有方法体,即都是没有实现的方法

3)在Golang中,一个自定义类型需要将某个接口的所有方法都实现,我们说这个自定义类型实现了该接口

4)一个自定义类型只有实现了某个接口,才能将该自定义类型的实例(变量)赋给接口类型

5)只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型(面试会问)

type integer int
type AInterface interface {
	Say()
}

func (i integer)Say() {
	fmt.Println("integer Say i = ",i)
}
func main(){
   var i integer = 10
   var b AInterface = i
   b.Say() //integer Say i =  10
}

6)一个自定义类型可以实现多个接口

package main
import (
	"fmt"
)

type AInterface interface {
	Say()

}

type Stu struct {
	Name string
}
func (stu Stu)Say(){
	fmt.Println("Stu Say()")
}

type integer int

func (i integer)Say() {
	fmt.Println("integer Say i = ",i)
}
type BInterface interface{
	Hello()
}
type Monster struct{

}
func (m Monster) Hello(){
	fmt.Println("Monster Hello()~~")
}
func (m Monster) Say(){
	fmt.Println("Monster Say()~~")
}
//此时刻Monster就实现了AInterface和BInterface

func main(){
   var stu Stu  //结构体变量,实现了Say() 实现了AInterface这个接口
   var a AInterface =stu
   a.Say() //Stu Say()
   var i integer = 10
   var b AInterface = i
   b.Say() //integer Say i =  10
//验证monster去实现两个接口
   var monster Monster
   var a2 AInterface = monster //Monster Say()~~
   var b2 BInterface = monster //Monster Hello()~~
   a2.Say()
   b2.Hello()
}

7)Golang接口中不能有任何变量

例如,以下写法就是错误的
type AInteger interface {
Name string//这是错误的,不能这样用
test()
}

8)一个接口(比如A接口)可以继承多个别的接口(比如B,C接口),这时如果要实现A接口,也必须将B,C接口的方法也全部实现

package main
import (
	"fmt"
)
type BInterface interface {
	test01()
}
type CInterface interface {
	test02()
}
type AInterface interface {
	BInterface
	CInterface
	test03()
}
//如果需要实现AIerface,就需要把BInterface和CInterface的方法都实现
type Stu struct{

}
//把所要实现的接口所有的方法都实现一下
func (stu Stu) test01(){
  fmt.Println("这是Test01")
}
func (stu Stu) test02(){
	fmt.Println("这是Test02")
}
func (stu Stu) test03(){
	fmt.Println("这是Test03")
}

func main(){
    //实践
	var stu Stu
	var a AInterface = stu
	a.test01()
	a.test02()
	a.test03()
}

9)interface类型默认是一个指针(引用类型),如果没有对interface初始化就使用,那么就会输出nil

10)空接口interface{}没有任何方法,所以所有类型都实现了空接口

type T interface {

}
func main(){
    //实践
	var stu Stu
	var a AInterface = stu
	a.test01()
	a.test02()
	a.test03()
	var t T =stu
	fmt.Println(t)
	var t2 interface{} = stu
	var num1 float64 = 8.8
	t2 = num1
	fmt.Println(t2,test02)
}

查看下列代码看看是否有错

type AInterface interface{
   Test01()
   Test02()
}
type BInterface interface{
   Test01()
   Test03()
}
type CInterface interface{
   AInterface
   BInterface
}
func main(){

}
//这里编译错误,因为CInterface有两个test01().编译器不通过

来看第二个代码

type Usb interface{
   Say()
}
type Stu struct {

}
func (this *Stu) Say() {
fmt,Println("Say()")
}

func main() {
var stu Stu = Stu{}
//var u Usb =stu //会报错,因为stu没有实现Say()方法
var u Usb = &stu //改正之后,加个地址就可以了
u.Say()
fmt.Println("here",u)
}

6.接口编程经典案例

实现对hero结构体切片的排序:sort.Sort(data Interface)

package main
import (
	"fmt"
	"sort"
	"math/rand"
)

//1.声明Hero结构体
type Hero struct {
	Name string
	Age int
}

//2.声明一个Hero的切片类型
type HeroSlice []Hero 

//3.实现Interface 接口
func (hs HeroSlice) Len() int {
	return len(hs )
}
//Less方法就是决定你是用什么标准进行排序
//1.按Hero的年龄从小到大进行排序!!
func (hs HeroSlice) Less(i,j int) bool {
	return hs[i].Age > hs[j].Age
	//修改成对姓名排序
    // return hs[i].Name > hs[j].Name
}

func (hs HeroSlice) Swap(i,j int) {
	// temp := hs[i]
	// hs[i] =hs[j]
	// hs[j] = temp
	//简洁的交换:下面一句话等价于上面三句话
	hs[i],hs[j] = hs[j],hs[i]
}

//声明一个Student结构体
//1.声明Student结构体
type Student struct {
	Name string
	Age int
	Score int
}
//然后将上面那三个方法复制到下面

//将student按成绩从大到小进行排序

//声明一个Stu切片类型
type StuSlice []Student
//3.实现Interface 接口
func (stu StuSlice) Len() int {
	return len(stu)
}
//Less方法就是决定你是用什么标准进行排序
//1.按Hero的年龄从小到大进行排序!!
func (stu StuSlice) Less(i,j int) bool {
	//按成绩进行排序
	return stu[i].Score > stu[j].Score
}

func (stu StuSlice) Swap(i,j int) {
	stu[i],stu[j] = stu[j],stu[i]
}



func main(){

	//先定义一个数组/切片
	var intSlice = []int{0,-1,10,7,90}
    //要求对intSlice切片进行排序
	//1.冒泡排序...
	//2.可以使用系统提供的方法
    sort.Ints(intSlice)
	fmt.Println(intSlice)//[-1 0 7 10 90]
	//请对结构体进行排序
	//1.冒泡排序
	//2.系统提供的方法

	//测试我们是否可以对结构体进行排序
	var heroes HeroSlice
	for i :=0;i < 10; i++{
		hero :=Hero {
			Name : fmt.Sprintf("英雄~%d",rand.Intn(100)),
			Age : rand.Intn(100),
		}
		//将hero append到heros切片
		heroes = append(heroes,hero)
	}
	//看看排序前的顺序
	for _, v := range heroes {
		fmt.Println(v)
	}
	fmt.Println( )
    //调用sort.Sort()
    sort.Sort(heroes)
    //看看排序后的顺序
	for _, v := range heroes {
		fmt.Println(v)
	}

	//这个接口的妙处就是将这个接口的三个方法实现然后只需要将结合挂钩梯放入到
	//sort方法中去就可以
	fmt.Println()

	var studentsl StuSlice
	for i :=0;i < 10; i++{
		stus :=Student {
			Name : fmt.Sprintf("学生~%d",rand.Intn(100)),
			Age : rand.Intn(100),
			Score : rand.Intn(100),
		}
		//将hero append到heros切片
		studentsl = append(studentsl,stus)
	}
	//看看排序前的顺序
	for _, v := range studentsl {
		fmt.Println(v)
	}
	fmt.Println( )
    //调用sort.Sort()
    sort.Sort(studentsl)
    //看看排序后的顺序
	for _, v := range studentsl {
		fmt.Println(v)
	}
}

7.接口与继承之间的比较

1)大家可能对实现接口和继承比较迷茫了。那么问题来了,那么他们究竟有什么区别呢?

例如有一个猴子会爬树,然而他想学鸟儿飞翔,鱼儿游泳

package main
import (
	"fmt"
)
//,Monkey结构体
type Monkey struct {
	Name string
}

//声明接口
type BirdAble interface {
	Flying()
}

//声明接口
type FishAble interface {
	Swimming()
}
func (this *Monkey) climbing() {
	fmt.Println(this.Name,"生来会爬树")
}

//创建LittleMonkey结构体
type LittleMonkey struct {
	Monkey //继承
}

//让littleMonkey实现BirdAble的Flying()方法
func (this *LittleMonkey) Flying(){
	fmt.Println(this.Name,"通过学习会飞翔")
}
//littleMonkey实现FishAble的Swimming()方法
func (this *LittleMonkey) Swimming(){
	fmt.Println(this.Name,"通过学习会游泳")
}
func main(){
    
	//创建LittleMonkey实例
	monkey := LittleMonkey{
		Monkey {
			Name : "悟空",
		},
	}
	monkey.climbing()
	monkey.Flying()
	monkey.Swimming()
  
}

对上面代码的小结

  1. 当A结构体继承了另外B结构体,那么A结构体就自动继承了B结构体的字段和方法,并且可以直接使用
  2. 当A结构体需要扩展功能,同时不希望去破坏继承关系,则可以去实现某个接口即可,因此我们可以认为:实现接口是对继承机制的补充。

实现接口可以看作是对继承的一种补充

在这里插入图片描述

  • 接口和继承解决的问题是不同的

继承的价值主要在于:解决代码的复用性可维护性

接口的价值主要在于:设计。设计好各种规范(方法),让其他自定义类型去实现这些方法

  • 接口比继承更加灵活 Person Student BirdAble LittleMonkey

  • 接口比继承更加灵活。继承是满足 is --a的关系。则接口只需满足like --a 的关系

  • 接口在一定程度上实现代码解耦

8.面向对象编程–多态

1)基本介绍

变量(实例)具有多种形态。面向对象的第三大特征,在Go语言,多态特征是通过接口实现的。可以按照统一的接口来调用不同的实现。这时接口变量就呈现不同的形态

2)快速入门

在前面的Usb接口案例:Usb usb 既可以接收手机变量,又可以接收相机变量,就体现了Usb接口多态特性。

//编写一个方法Working方法,接收一个Usb接口类型变量
//只要是实现了Usb接口(所谓实现Usb接口,就是指实现了Usb接口声明所有方法)
func (c Computer) Working (usb Usb){//usb变量会根据传入的实参,来判断到底是Phone还是Camera
	//通过usb接口变量来调用Start和Stop方法
     usb.Start()
	 usb.Stop()
}
func main(){

	//测试
	//先创建结构体变量
	computer :=Computer{}
	phone :=Phone{}
	camera := Camera{}

	//关键点
	computer.Working(phone)//传入phon就是phon执行这个方法
	computer.Working(camera)

}
3)接口体现多态的两种形式

多态参数

在前面的Usb接口案例,Usb usb,既可以接收手机变量,又可以接收相机变量,就体现了Usb的接口多态

多态数组

演示一个案例给Usb数组,存放phone结构体和Camera结构体变量

```go
package main
import (
	"fmt"
)

//声明定义一个接口
type Usb interface{
	Start()
	Stop()
}

type Phone struct {
    name string
}

type Camera struct {
	name string
}
//让phone实现usb接口的方法
func (p Phone) Start(){
	fmt.Println("手机开始工作。。。")
}
func (p Phone) Stop(){
	fmt.Println("手机停止工作。。。")
}

func (c Camera) Start(){
	fmt.Println("相机开始工作。。。")
}
func (c Camera) Stop(){
	fmt.Println("相机停止工作。。。")
}
//计算机
type Computer struct{

}

//编写一个方法Working方法,接收一个Usb接口类型变量
//只要是实现了Usb接口(所谓实现Usb接口,就是指实现了Usb接口声明所有方法)
func (c Computer) Working (usb Usb){
	//通过usb接口变量来调用Start和Stop方法
     usb.Start()
	 usb.Stop()
}
func main(){
   //定义一个Usb接口数组,可以存放Phone和Camera的结构体变量
   //这里就体现出多态数组
   var usbArr  [3]Usb
   usbArr[0] = Phone{"iphone"}
   usbArr[1] = Phone{"小米"}
   usbArr[2] = Camera{"佳能"}
   fmt.Println(usbArr) //[{iphone} {小米} {佳能}]
	
}
```




9.类型断言

1)先看一个需求

代码

type Point struct{
     x int
     y int
}
func main() {
    var a interface{}
    var point Point = Pooint{1,2}
    a = point //OK
    //如何将A赋给一个Point变量?
    var b Point
    b = a /可以吗? ==》erro
    fmt.Println(b)
}
//改进之后
package main
import (
	"fmt"
)
type Point struct{
	x int
	y int
}
func main() {
   var a interface{}
   var point Point = Point{1,2}
   a = point //OK
   //如何将A赋给一个Point变量?
   var b Point
   //b = a //可以吗? ==》erro
   b = a.(Point) //解决办法,类型断言
    //b = a.(Point)就是类型断言,表示判断a是否指向Poin类型的变量,如果是就转成了Point类型并赋给b变量,否则报错
   fmt.Println(b) //1 2
}

有一个具体的需要,引出了类型断言

2)基本介绍

类型断,由于接口是一般类型,不知道具体类型,如果要转成具体类型,就需要使用类型断言,具体的如下

//float32可以是其他类型,比如Point
var t float32
var x interface{}
x = t //OK
y := x.(float32)//转成float32



//float32可以死其他类型,比如Point
var t float32 
var x interface{}
x = t
//转成float,待检查的
y,ok :=a.(float32)
if ok == true {
fmt.Println("convert success")
}else{
fmt.Println("convert fall")
}


/类型断言的其他案例
   var x interface{}
   var b2 float32 = 1.1
   x = b2 //空接口可以接收任意类型
   //x = >float32 【使用类型断言】
   y := x.(float32)
   fmt.Printf("y的类型是%T 值是%v",y,y) //y的类型是float32 值是1.1

对上面的代码的说明

在进行类型断言时,如果类型不匹配,就会报panic,因此进行类型断言时,要确保原来的空接口指向的就是断言的类型

如何在进行断言时带上检测机制,如果成功就ok否则也不要报panic

//类型断言(带检测)
var x interface{}
var b2 float32 = 1.1
x = b2 //空接口可以接收任意类型
//x = >float32 【使用类型断言】
//y,ok := x.(float64)
//简写

if  y,ok := x.(float64);ok {
	fmt.Println("转换成功了")
    fmt.Printf("y的类型是%T 值是%v",y,y) //y的类型是float32 值是1.1
}else{
	fmt.Println("转换失败")
}
fmt.Println("检测失败了无妨,代码不要停")

}
3)类型断言的最佳实践1

在前面的Usb接口案例做改进

给Phone结构体增加一个特有的方法call(),当Usb接口接收的是Phone变量时,还需要调用call方法。

package main
import (
	"fmt"
)

//声明定义一个接口
type Usb interface{
	Start()
	Stop()
}

type Phone struct {
    name string
}

type Camera struct {
	name string
}
//让phone实现usb接口的方法
func (p Phone) Start(){
	fmt.Println("手机开始工作。。。")
}
func (p Phone) Stop(){
	fmt.Println("手机停止工作。。。")
}

func (p Phone) Call(){
	fmt.Println("手机开始打电话。。。")
}


func (c Camera) Start(){
	fmt.Println("相机开始工作。。。")
}
func (c Camera) Stop(){
	fmt.Println("相机停止工作。。。")
}
//计算机
type Computer struct{

}

//编写一个方法Working方法,接收一个Usb接口类型变量
//只要是实现了Usb接口(所谓实现Usb接口,就是指实现了Usb接口声明所有方法)
func (c Computer) Working (usb Usb){
	//通过usb接口变量来调用Start和Stop方法
     usb.Start()
	 //如果usb是指向Phone结构体变量,则还需要调用Call()方法
	 //类型断言
	 if phone, ok := usb.(Phone); ok {
		phone.Call()
	 }//否则断言失败还是继续执行下列方法
	 usb.Stop()
}

func main(){
   //定义一个Usb接口数组,可以存放Phone和Camera的结构体变量
   //这里就体现出多态数组
   var usbArr  [3]Usb
   usbArr[0] = Phone{"iphone"}
   usbArr[1] = Phone{"小米"}
   usbArr[2] = Camera{"佳能"}
   //fmt.Println(usbArr) //[{iphone} {小米} {佳能}]
   //遍历
   var computer Computer
   for _,v := range usbArr{
          computer.Working(v)
		  fmt.Println()
   }
	
}
执行结果如下:
手机开始工作。。。
手机开始打电话。。。
手机停止工作。。。

手机开始工作。。。
手机开始打电话。。。
手机停止工作。。。

相机开始工作。。。
相机停止工作。。。

4)类型断言实践2

写一个函数,循环判断传入参数的类型

package main
import (
	"fmt"
)
//编写一个函数,可以判断输入的参数是什么类型
func TypeJudge(items... interface{}){
	for index, x := range items {
        switch x.(type) {
			case bool : 
				fmt.Printf("第%v个参数是 bool 类型,值是%v\n",index+1,x)
			case float32 : 
				fmt.Printf("第%v个参数是 float32 类型,值是%v\n",index+1,x)
			case float64 : 
				fmt.Printf("第%v个参数是 float64 类型,值是%v\n",index+1,x)	
			case int, int32, int64 : 
				fmt.Printf("第%v个参数是 整数 类型,值是%v\n",index+1,x)		  	  
			case string : 
				fmt.Printf("第%v个参数是 string 类型,值是%v\n",index+1,x)
			default :
			    fmt.Printf("第%v个参数是 类型 不确定,值是%v\n",index+1,x)	
		 }
	}
	
}
func main(){
	var n1 float32 = 1.1
	var n2 float64 = 2.3
	var n3 int32 = 30
	var name = "tom"
	address := "北京"
	n4 :=300
    
	TypeJudge(n1,n2,n3,name,address,n4)

}
//运行结果如下1个参数是 float32 类型,值是1.12个参数是 float64 类型,值是2.33个参数是 整数 类型,值是304个参数是 string 类型,值是tom
第5个参数是 string 类型,值是北京
第6个参数是 整数 类型,值是300

5)类型断言的最佳实践3

在前面代码的基础上,增加判断Student类型和*Student类型

package main
import (
	"fmt"
)

//定义Student类型
type Student struct {

}
//编写一个函数,可以判断输入的参数是什么类型
func TypeJudge(items... interface{}){
	for index, x := range items {
        switch x.(type) {
			case bool : 
				fmt.Printf("第%v个参数是 bool 类型,值是%v\n",index+1,x)
			case float32 : 
				fmt.Printf("第%v个参数是 float32 类型,值是%v\n",index+1,x)
			case float64 : 
				fmt.Printf("第%v个参数是 float64 类型,值是%v\n",index+1,x)	
			case int, int32, int64 : 
				fmt.Printf("第%v个参数是 整数 类型,值是%v\n",index+1,x)		  	  
			case Student : 
				fmt.Printf("第%v个参数是 Student 类型,值是%v\n",index+1,x)
			case *Student : 
				fmt.Printf("第%v个参数是 *Student 类型,值是%v\n",index+1,x)
			case string : 
				fmt.Printf("第%v个参数是 string 类型,值是%v\n",index+1,x)
						
			default :
			    fmt.Printf("第%v个参数是 类型 不确定,值是%v\n",index+1,x)	
		 }
	}
	
}


func main(){
	var n1 float32 = 1.1
	var n2 float64 = 2.3
	var n3 int32 = 30
	var name = "tom"
	address := "北京"
	n4 :=300

	stu1 := Student{}
	stu2 := &Student{}
    
	TypeJudge(n1,n2,n3,name,address,n4,stu1,stu2)

}

数是什么类型
func TypeJudge(items… interface{}){
for index, x := range items {
switch x.(type) {
case bool :
fmt.Printf(“第%v个参数是 bool 类型,值是%v\n”,index+1,x)
case float32 :
fmt.Printf(“第%v个参数是 float32 类型,值是%v\n”,index+1,x)
case float64 :
fmt.Printf(“第%v个参数是 float64 类型,值是%v\n”,index+1,x)
case int, int32, int64 :
fmt.Printf(“第%v个参数是 整数 类型,值是%v\n”,index+1,x)
case Student :
fmt.Printf(“第%v个参数是 Student 类型,值是%v\n”,index+1,x)
case *Student :
fmt.Printf(“第%v个参数是 *Student 类型,值是%v\n”,index+1,x)
case string :
fmt.Printf(“第%v个参数是 string 类型,值是%v\n”,index+1,x)

		default :
		    fmt.Printf("第%v个参数是 类型 不确定,值是%v\n",index+1,x)	
	 }
}

}

func main(){
var n1 float32 = 1.1
var n2 float64 = 2.3
var n3 int32 = 30
var name = “tom”
address := “北京”
n4 :=300

stu1 := Student{}
stu2 := &Student{}

TypeJudge(n1,n2,n3,name,address,n4,stu1,stu2)

}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1200289.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

odoo16 库存初始化 excel导入问题2

产品导入模板: excel内容: 导入测试 查看可能的值,发现没有ml,在计量单位中增加ml选项(不选创建,知道为什么不,仔细想想,创建不知ml是什么单位) 位置不能在此导入,故取消 测试正常 导入成功 总结:产品导入时,位置无法指定,只建产品名称,计量单位,采购单位,

混沌系统在图像加密中的应用(基于哈密顿能量函数的混沌系统构造1.3)

混沌系统在图像加密中的应用&#xff08;基于哈密顿能量函数的混沌系统构造1.3&#xff09; 前言一类三维非哈密顿系统的构造与动态特性分析1.相关理论基础2.类Nos-Hoove系统构造的思路及实现3.基于哈密顿能量理论的Nos-Hoove系统的分析与仿真3.1 平衡点分析3.2 不同强度激励下…

软件设计师 之 【第三章】数据库系统

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 1、数据库系统前言 2、三级模式 - 两级映射…

数据结构 | 带头双向循环链表专题

数据结构 | 带头双向循环链表专题 前言 前面我们学了单链表&#xff0c;我们这次来看一个专题带头的双向循环链表~~ 文章目录 数据结构 | 带头双向循环链表专题前言带头双向循环链表的结构实现双向链表头文件的定义哨兵位初始化创建节点尾插尾删头插头删打印查找指定位置前插入…

DevChat 初探之 RBAC 模型的实现

今天我们来尝试一款编程辅助助手 DevChat, 看能不能提升咱们的日常编程效率。作为一款编程助手&#xff0c;我们来看看它与 Copilot, CodeWhisperer 同领域产品的一些区别和特色。定个小目标&#xff0c;通过 DevChat 实现一个简单的 RBAC 模型&#xff0c;小试牛刀一下&#x…

虚拟机CentOS 8 重启后不能上网

情况说明&#xff1a;原本虚拟机是可以上网的&#xff0c;然后嘚一下&#xff0c;重启后&#xff0c;连接不上网络&#xff0c;完了&#xff0c;上网查找一堆质料&#xff0c;我的连接方式是桥接模式&#xff08;复制物理网络连接状态&#xff09;。 好&#xff0c;有人说是vmn…

C++: 内存管理 (new / delete)

文章目录 一. C/C 内存分布二. C 语言中动态内存管理方式: malloc/calloc/realloc/free三. C内存管理方式1. new / delete 操作内置类型2. new / delete 操作自定义类型 四. operator new 与 operator delete 函数五. new 和 delete 的实现原理1. 内置类型2. 自定义类型 六. 定…

双11终极官方战报 凯迪仕智能锁全网全渠道第一 持续领跑智能锁行业

一年一度双11狂欢盛典暂时落下帷幕&#xff0c;作为下半年最大的电商购物节&#xff0c;本次双11电商平台借机推出优惠券、补贴、折扣等促销活动&#xff0c;激发消费者购物热情。其中&#xff0c;智能门锁等智能家居产品更是取得了亮眼的成交。 据悉&#xff0c;凯迪仕智能锁双…

自定义Graph Component:1-开发指南

可以使用自定义NLU组件和策略扩展Rasa&#xff0c;本文提供了如何开发自己的自定义Graph Component指南。   Rasa提供各种开箱即用的NLU组件和策略。可以使用自定义Graph Component对其进行自定义或从头开始创建自己的组件。   要在Rasa中使用自定义Graph Component&#x…

Pinia 状态管理器 菠萝:Setup Store风格

Pinia介绍&#xff1a; Pinia 是 Vue 的专属状态管理库&#xff0c;它允许你跨组件或页面共享状态。 Pinia 大小只有 1kb 左右&#xff0c;超轻量级&#xff0c;你甚至可能忘记它的存在&#xff01; 相比 Vuex,Pinia 的优点&#xff1a; 更贴合 Vue 3 的 Composition API 风…

C语言从入门到精通之【数据类型和关键字】

数据类型在程序使用之前已经预先设定好了&#xff0c;在整个程序的运行过程中没有变化&#xff0c;这些称为常量&#xff08;constant&#xff09;。其他数据类型在程序运行期间可能会改变或被赋值&#xff0c;这些称为变量&#xff08;variable&#xff09;。 变量类型有几种…

golang Copier 数据复制

Copier I am a copier, I copy everything from one to another Copier是golang实现的&#xff0c;实现不同数据结构之间数据复制的工具包 github地址 使用方法 以User和Employee之间相互复制为例 使用的版本为 v0.3.5 入门 package mainimport ("fmt""git…

基于SSM的数据结构课程网络学习平台

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

BM65 最长公共子序列(二)

动态规划 BM65 最长公共子序列&#xff08;二&#xff09; 这道题是动态规划的典型例题。 思路 题目要求获取最长公共子序列&#xff0c;我们要先求最长公共子序列的长度&#xff0c;然后根据这个长度倒推从而获取这个子序列。注意&#xff1a;子序列不是子串&#xff0c;子…

springboot的配置信息的设置和读取(application.properties/application.yml)

springboot提供了两种配置信息的文件格式&#xff0c;application.properties和application.yml&#xff0c;基于直接明了&#xff0c;使用方便和高效的前提下下面的配置均采用yml格式配置&#xff0c; 注意 yml采用缩减方式来排列键后面紧跟冒号&#xff0c;然后空格&#x…

数据结构—内部排序(上)

文章目录 8.内部排序(上)(1).排序基础#1.为什么是内部排序#2.排序的稳定性 (2).冒泡排序#1.算法思想#2.代码实现#3.稳定性与时间复杂度分析 (3).选择排序#1.算法思想#2.代码实现#3.稳定性与时间复杂度分析 (4).插入排序#1.算法思想#2.代码实现#3.稳定性与时间复杂度分析 (5).希…

文心一言 VS 讯飞星火 VS chatgpt (133)-- 算法导论11.2 5题

五、用go语言&#xff0c;假设将一个具有n个关键字的集合存储到一个大小为 m 的散列表中。试说明如果这些关键字均源于全域U&#xff0c;且|U|>nm&#xff0c;则U 中还有一个大小为n 的子集&#xff0c;其由散列到同一槽位中的所有关键字构成&#xff0c;使得链接法散列的查…

三分钟学完Git版本控制常用指令

基本指令 git clone [url] 克隆远程仓库到本地 git clone https://gitee.com/mayun2023a/mprpc.git2.git checkout -b xxx 切换至新分支xxx&#xff08;相当于复制了remote的仓库到本地的xxx分支上) 3.修改或者添加本地代码&#xff08;部署在硬盘的源文件上&#xff09; 4.g…

LabVIEW中如何在网络上使用远程VI服务器

LabVIEW中如何在网络上使用远程VI服务器 如何在网络上使用远程VI服务器&#xff1f; 解答: 首先&#xff0c;需要在远程的计算机上打开一个在VI服务器上的LabVIEW应用程序的引用。这可以通过“Open ApplicationReference“函数实现。然后用“Open VI Reference”函数打开一个…

【入门Flink】- 10基于时间的双流联合(join)

统计固定时间内两条流数据的匹配情况&#xff0c;需要自定义来实现——可以用窗口&#xff08;window&#xff09;来表示。为了更方便地实现基于时间的合流操作&#xff0c;Flink 的 DataStrema API 提供了内置的 join 算子。 窗口联结&#xff08;Window Join&#xff09; 一…