当前位置: 首页 > news >正文

Golang--面向对象

Golang语言面向对象编程说明:

  • Golang也支持面向对象编程(OOP),但是和传统的面向对象编程有区别,并不是纯粹的面向对象语言。所以我们说Golang支持面向对象编程特性是比较准确的。
  • Golang没有类(class),Go语言的结构体(struct)和其它编程语言的类(class)有同等的地位,可以理解Golang是基于struct来实现OOP特性的。
  • Golang面向对象编程非常简洁,去掉了传统OOP语言的方法重载、构造函数和析构函数、隐藏的this指针等等
  • Golang仍然有面向对象编程的继承,封装和多态的特性,只是实现的方式和其它OOP语言不一样,比如继承:Golang没有extends 关键字,继承是通过匿名字段来实现。 

1、结构体

package main
import "fmt"//定义结构体
type Stu struct{//变量名字大写外界可以访问,小写外界不能访问Name stringAge intNum string
}func main(){//创建结构体实例var stu1 Stufmt.Println(stu1)//在未赋值时默认值:{ 0 }	stu1.Name = "张三"	stu1.Age = 18stu1.Num = "1001"fmt.Println(stu1)//创建结构体实例var stu2 Stu = Stu{"李四",19,"1002"}fmt.Println(stu2)//创建结构体实例var stu3 = Stu{"王五",20,"1003"}fmt.Println(stu3)//创建结构体实例stu4 := Stu{"赵六",21,"1004"}fmt.Println(stu4)//创建结构体实例   指针类型stu5 := &Stu{"田七",22,"1005"}fmt.Println(stu5)//创建结构体实例   指针类型stu6 := &Stu{"周八",23,"1006"}fmt.Println(stu6)//创建结构体实例stu7 := new(Stu)stu7.Name = "吴九"stu7.Age = 24stu7.Num = "1007"fmt.Println(stu7)
}

1.1 结构体实例创建

package main
import "fmt"//定义结构体
type Stu struct{//变量名字大写外界可以访问,小写外界不能访问Name stringAge intNum string
}func main(){//方式一:直接创建var s1 Stus1.Name = "张三"s1.Age = 18s1.Num = "1001"fmt.Println(s1)fmt.Printf("%T\n",s1) // 输出的是结构体的类型--> main.Stu//方式二:创建时直接赋值var s2 = Stu{"李四",19,"1002"}fmt.Println(s2)//方式三:new关键字创建,返回结构体指针var p *Stu = new(Stu)(*p).Name = "王五"(*p).Age = 20p.Num = "1003"     // 结构体指针可以直接访问结构体成员(简化)fmt.Println(*p)    // 输出的是结构体的值fmt.Println(p)     // 输出的是结构体的地址//方式四:返回结构体指针var p2 = &Stu{"赵六",21,"1004"}p2.Age = 11fmt.Println(*p2)    //输出的是结构体的值fmt.Println(p2)     //输出的是结构体的地址fmt.Printf("%p\n",p2)  // 输出的是结构体的地址fmt.Printf("%T\n",p2)  // 输出的是结构体的类型--> *main.Stu
}

1.2 创建结构体实例时指定字段值

package main
import "fmt"type Stu struct{Age intName string
}func main(){//方式一:按照顺序赋值--缺点:如果顺序改变,就会报错s := Stu{10,"张三"}fmt.Println(s)//方式二:按照指定变量赋值,可以不按照顺序赋值s1 := Stu{Name:"李四",Age:11,     // 分行赋值,最后一行需要加逗号}fmt.Println(s1)//方式三:想要返回结构体的指针类型s3 := &Stu{12,"王五"}fmt.Println(s3) // &{12 王五}fmt.Println(*s3) //{12 王五}
}

1.3 跨包创建结构体实例

  1. 创建不同的包
  2. student --> package model
  3. main.go --> package main


     

结构体名字首字母小写,并可以进行跨包访问  -->  工厂模式


 

1.4 结构体之间的转换

1、结构体是用户单独定义的类型,和其它类型进行转换时需要有完全相同的字段(名字、个数、类型、顺序需要完全一致)

package main
import "fmt"type Stu struct{Age intName string
}type Person struct{Age intName string
}func main(){s1 := Stu{18,"张三"}p1 := Person{19,"李四"}p1 = Person(s1)fmt.Println(s1)fmt.Println(p1)
}

2、 结构体进行type重新定义(相当于取别名),Golang认为是新的数据类型,但是相互间可以强转

package main
import "fmt"type Stu struct{Age intName string
}
type Per Stufunc main(){var s1 Stu = Stu{20,"张三"}var p1 Per = Per{19,"李四"}p1 = Per(s1)fmt.Println(s1)       // 输出的是结构体的值fmt.Printf("%T\n",s1) // 输出的是结构体的类型--> main.Stufmt.Println(p1)       // 输出的是结构体的值fmt.Printf("%T\n",p1) // 输出的是结构体的类型--> main.Per
}

2、方法

方法:指作用在指定的数据类型上,和指定的数据类型绑定,因此自定义类型都可以方法,不仅仅时struct。

函数:函数是独立的代码块,可以接受参数并返回结果。

区别:

  • 函数:不需要接收者,可以被独立调用。
  • 方法:必须有一个接收者,该接收者可以是一个值(值接收者)或指针(指针接收者),并且在调用方法时,需要通过接收者的实例来调用。

调用:

package main
import "fmt"type Stu struct{Age intName string
}//(s Stu)用于给Stu绑定Print方法,s Stu表示接收者
//结构体传递是值传递,不影响原结构体的值
func (s Stu) Print(){s.Age = 100fmt.Println(s.Age,s.Name) // {100 张三}
}func main(){var s1 Stu = Stu{20,"张三"}s1.Print()      //{100 张三}fmt.Println(s1) //{20 张三}
}

注意:

  • 结构体和方法绑定,调用该方法时必须靠指定的类型(其他类型变量调用会报错)
  • 结构体对象传入方法中,是进行了值传递(副本),副本改变不影响原结构体
  • 结构体对象传入方法中,如果需要在方法中改变原结构体的值,可以通过结构体指针的方式来处理
    package main
    import "fmt"type Stu struct{Age intName string
    }//(s Stu)用于给Stu绑定Print方法,s Stu表示接收者
    //结构体传递是值传递,不影响原结构体的值
    func (s *Stu) Print(){s.Age = 100 // 结构体指针可以直接访问结构体成员(简化)fmt.Println(s.Age,s.Name) // {100 张三}
    }func main(){var s1 Stu = Stu{20,"张三"}(&s1).Print()      //或者是s1.Print(),都可以实现调用fmt.Println(s1) //{100 张三}
    }
  • Golang中的方法作用在指定的数据类型上的,和指定的数据类型绑定,因此自定义类型都可以有方法,而不仅仅时struct,比如int,float32等都可以有方法(借用type来给基本数据类型取别名,Golang认为是新的数据类型,用这个特性来绑定方法)

    package main
    import "fmt"type interger intfunc (i interger) Print(){i = 11111111fmt.Println(i) // 11111111//fmt.Printf("%T\n",i) // main.interger
    }
    func (i *interger) change(){*i = 1111fmt.Println(*i)
    }func main(){var i interger = 100i.Print() // 11111111fmt.Println(i) // 100--不改变i.change() //1111fmt.Println(i) //1111--改变
    }
  • 方法的访问范围控制的规则,和函数一样。方法名首字母小写,只能在本包访问;方法首字母大写,可以在本包和其他包访问
  • 如果一个类型实现了String()这个方法,那么fmt.Println默认会调用这个变量的String()进行输出
    package main
    import "fmt"type Stu struct{Age intName string
    }
    func (s *Stu) String() string{str := fmt.Sprintf("Age:%d Name:%s",s.Age,s.Name)return str
    }// func (s Stu) String() string{
    // 	str := fmt.Sprintf("Age:%d Name:%s",s.Age,s.Name)
    // 	return str
    // }func main(){var s Stu = Stu{10,"张三"}fmt.Println(&s)//fmt.Println(s)
    }

简化:

  • 使用结构体或结构体指针调用变量或方法时,指针调用可以不用*
  • 使用结构体或结构体指针作为参数传参时,结构体传给结构体指针可以不用&(对于方法来说,接收者为值类型,可以传入指针类型(但还是值传递),接收者为指针类型,可以传入值类型)

3、封装

什么是封装:
封装就是把抽象出的字段和对字段的操作封装在一起,数据被保护在内部,程序的其它包只有通过被授权的操作方法,才能对字段进行操作

封装的好处:

  • 隐藏实现细节
  • 可以对数据进行验证,保证安全合理

Golang中如何实现封装:

  • 建议将结构体、字段(属性)的首字母小写(其它包不能使用,类似private,实际开发不小写也可能,因为封装没有那么严格)
  • 给结构体所在包提供一个工厂模式的函数,首字母大写(类似一个构造函数)
  • 提供一个首字母大写的Set方法(类似其它语言的public),用于对属性判断并赋值
  • 提供一个首字母大写的Get方法(类似其它语言的public),用于获取属性的值

4、继承

当多个结构体存在相同的属性(字段)和方法时,可以从这些结构体中抽象出结构体,在该结构体中定义这些相同的属性和方法,其它的结构体不需要重所定义这些属性和方法,只需嵌套一个匿名结构体即可在Golang中,如果一个struct嵌套了另一个匿名结构体,那么这个结构体可以直接访问匿名结构体的字段和方法,从而实现了继承特性。(提高代码复用性和扩展性)

package main
import "fmt"type Animal struct{Age int;Wei int;
}func (an *Animal) Eat(name string){fmt.Printf("%s: eat\n",name)
}
func (an *Animal) Run(name string){fmt.Printf("%s: run\n",name)
}type Dog struct{AnimalName string
}
func (dog *Dog) Shout(){fmt.Println("汪")
}type Cat struct{AnimalName string
}
func (cat *Cat)Shout(){fmt.Println("喵")
}func main(){var cat Cat = Cat{Animal{10,10},"小白"}var dog Dog = Dog{Animal{6,20},"小黑"}//catcat.Animal.Eat(cat.Name) // 小白: eatcat.Animal.Run(cat.Name) // 小白: runcat.Shout() // 喵//dogdog.Animal.Eat(dog.Name) // 小黑: eatdog.Animal.Run(dog.Name) // 小黑: rundog.Shout() // 汪
}

注意:

  • 结构体可以使用嵌套匿名结构体所有的字段和方法,即:首字母大写或者小写的字段、方法,都可以使用
  • 匿名结构体字段访问可以简化(例如:cat.Animal.Eat(cat.Name) -->  cat.Eat(car.Name) )
    调用过程:cat.Eat(car.Name)先在对应的Cat结构体中找是否有Eat方法,如果有则直接访问;如果没有则就去找嵌入的结构体中继续寻找(就近原则)
  • 当结构体和匿名结构体有相同的字段或者方法时,编译器采用就近访间原则访问,如希望访问匿名结构体的字段和方法,可以通过匿名结构体名来区分
  • Golang中支持多继承:如一个结构体嵌套了多个匿名结构体,那么该结构体可以直接访问嵌套的匿名结构体的字段和方法,从而实现了多重继承。为了保证代码的简洁性,建议大家尽量不使用多重继承,很多语言就将多重继承去除了(可能出现菱形继承的问题),但是Go中保留了
  • 嵌入的匿名结构体有相同的字段名或者方法名,则在访问时,需要通过指明匿名结构体类型名来区分。
  • 结构体的匿名字段可以是基本数据类型(这与既不继承没关系)
    package main
    import "fmt"type Animal struct{int
    }	func main(){var a Animal = Animal{10}fmt.Println(a.int) // 10
    }
  • 嵌套匿名结构体后,也可以在创建结构体变量(实例)时,直接指定各个匿名结构体字段的值

  • 嵌入匿名结构体的指针也是可以的

  • 结构体的字段可以是结构体类型的(组合模式) 

5、接口

package main
import "fmt"//接口的定义:定义规则,定义规范,定义某种能力
//interface接口类型
type SayHello interface{//只声明,没有实现的方法sayHello()
}
//接口的实现:定义一个结构体
type Chinese struct{}
//实现接口的方法--具体的实现
func (ch Chinese) sayHello(){fmt.Println("你好")
}//接口的实现:定义一个结构体
type American struct{}
//实现接口的方法--具体的实现
func (am American) sayHello(){fmt.Println("hello")
}
//定义一个函数:接收具备SayHello接口的能力的变量、
func greet(s SayHello){s.sayHello()
}func main(){c := Chinese{}a := American{}//调用函数greet(c)greet(a)
}
  • 接口中可以定义一组方法,但不需要实现。并且接口中不能包含任何变量。到某个自定义类型要使用的时候(实现接口的时候),再根据具体情况把这些方法具体实现出来。
  • 实现接口要实现所有的方法
  • Golang中实现接口是基于方法的,不是基于接口的(例如:A接口有a和b方法,B接口有a和b方法,C结构体实现了a和b方法,那么C实现了A接口,也实现了B接口。只要实现全部方法即可。和实际接口耦合性很低)
  • 接口目的是为了定义规范,具体由别人来实现即可
  • 接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量
    //SayHello是接口类型//直接用接口创建实例,会出错:
    var s SayHello   //error
    s.sayHello()       //error//但是可以指向一个实现了该接口的自定义类型的变量
    //American -> 实现了接口的自定义类型
    var am American
    var s SayHello = am
    s.sayHello()
  • 只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型
    package main
    import "fmt"type Print interface{print()
    }type interger int
    func (i interger)print(){fmt.Printf("%T:%d\n",i,i)
    }type str string
    func (s str)print(){fmt.Printf("%T:%s\n",s,s)
    }func f(p Print){p.print()
    }func main(){var i interger = 11111var s str = "hello"f(i) //main.interger:11111f(s) //main.str:hello
    }
  • 一个自定义类型可以实现多个接口
  • 一个接口(比如A接口)可以继承多个别的接口(比如B、C接口),这时如果要实现A接口,也必须将B、C接口的方法也全部实现
    package main
    import "fmt"type A interface{a()
    }
    type B interface{b()
    }
    //C接口继承AB接口
    type C interface{ABc()
    }type D struct{}
    func (d D)a(){fmt.Println("a")
    }
    func (d D)b(){fmt.Println("b")
    }
    func (d D)c(){fmt.Println("c")
    }func Print(c C){c.a()c.b()c.c()
    }func main(){d := D{}Print(d) //a b c
    }
  • interface类型默认是一个指针(引用类型),如果没有对interface初始化就使用,那么会输出nil
  • 空接口没有任何方法,所以可以理解为所有类型都实现了空接口,也可以理解为我们可以把任何一个变量赋值给空接口
    var s str = str{}
    var a interface{} = s


     

6、多态

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

package main
import "fmt"//接口的定义:定义规则,定义规范,定义某种能力
//interface{} 空接口,没有任何方法
type SayHello interface{//只声明,没有实现的方法sayHello()
}
//接口的实现:定义一个结构体
type Chinese struct{}
//实现接口的方法--具体的实现
func (ch Chinese) sayHello(){fmt.Println("你好")
}//接口的实现:定义一个结构体
type American struct{}
//实现接口的方法--具体的实现
func (am American) sayHello(){fmt.Println("hello")
}
//定义一个函数:接收具备SayHello接口的能力的变量、
func greet(s SayHello){  s.sayHello()        //s可以通过上下文识别具体是什么类型的实例,这就体现了多态
}func main(){c := Chinese{}a := American{}//调用函数greet(c)greet(a)
}

接口体现多态特征:

  1. 多态参数:例如上面greet函数中的s变量
  2. 多态数组:比如上面的示例中,定义SayHello数组,存放中国人结构体和美国人结构体
    package main
    import "fmt"//接口的定义:定义规则,定义规范,定义某种能力
    //interface{} 空接口,没有任何方法
    type SayHello interface{//只声明,没有实现的方法sayHello()
    }
    //接口的实现:定义一个结构体
    type Chinese struct{}
    //实现接口的方法--具体的实现
    func (ch Chinese) sayHello(){fmt.Println("你好")
    }//接口的实现:定义一个结构体
    type American struct{}
    //实现接口的方法--具体的实现
    func (am American) sayHello(){fmt.Println("hello")
    }
    //定义一个函数:接收具备SayHello接口的能力的变量、
    func greet(s SayHello){s.sayHello()
    }func main(){//定义一个多态数组--接口类型可以存储任何实现了该接口的变量var arr [3]SayHelloarr[0] = Chinese{}arr[1] = American{}arr[2] = Chinese{}//遍历数组for i := 0;i < len(arr);i++{greet(arr[i]) // 你好 hello 你好}
    }
    


     

7、断言

  • 在Go语言中,断言(Type Assertion)是一种用于检查接口变量的动态类型是否与指定类型相匹配的操作。它允许你将一个接口类型的变量转换为具体的类型以便访问该类型的特定方法或字段。
  • 断言的语法是 x.(T),其中 x 是一个接口类型的变量,T 是你想要断言的具体类型。
  • 如果 x 的动态类型确实是 T,那么断言会成功,并且返回 T 类型的值。如果断言失败,程序会抛出一个运行时错误。
  • 断言语法x.(T)的返回值 -> 变量,flag -> 变量用于接收T类型的值,flag用于判断类型是否转化成功 -> true--成功,false--失败。
  • 类型断言通常用于确保在调用特定方法或访问特定字段之前,接口变量确实是你所期望的类型。这有助于避免在运行时出现类型不匹配的错误。
package main
import "fmt"//接口的定义:定义规则,定义规范,定义某种能力
//interface{} 空接口,没有任何方法
type SayHello interface{//只声明,没有实现的方法sayHello()
}
//接口的实现:定义一个结构体
type Chinese struct{}
//实现接口的方法--具体的实现
func (ch Chinese) sayHello(){fmt.Println("你好")
}
func (ch Chinese) gongxi(){fmt.Println("恭喜发财")
}//接口的实现:定义一个结构体
type American struct{}
//实现接口的方法--具体的实现
func (am American) sayHello(){fmt.Println("hello")
}
//定义一个函数:接收具备SayHello接口的能力的变量、
func greet(s SayHello){s.sayHello()ch,flag := s.(Chinese)// 类型断言:看s是否能转成Chinese类型并赋给ch变量//就是把结构体转换成能实现当前接口的结构体,如果能转成,就赋值给ch,不能转成,就报错if flag==true {    //或者是 if ch,flag := s.(Chinese); flag{ch.gongxi()}else{fmt.Println("类型断言失败,美国人不会恭喜发财")}
}func main(){var ch Chinese = Chinese{}var am American = American{}greet(ch) // 你好 恭喜发财greet(am) // hello 类型断言失败,美国人不会恭喜发财
}

Type Switch的基本用法

Type Switch是Go语言中一种特殊的switch语法,它比较的是类型而不是具体的值。它判断某个接口变量的类型,然后根据具体类型再做相应处理。

package main
import "fmt"//接口的定义:定义规则,定义规范,定义某种能力
//interface{} 空接口,没有任何方法
type SayHello interface{//只声明,没有实现的方法sayHello()
}
//接口的实现:定义一个结构体
type Chinese struct{}
//实现接口的方法--具体的实现
func (ch Chinese) sayHello(){fmt.Println("你好")
}
func (ch Chinese) gongxi(){fmt.Println("恭喜发财")
}//接口的实现:定义一个结构体
type American struct{}
//实现接口的方法--具体的实现
func (am American) sayHello(){fmt.Println("hello")
}
//定义一个函数:接收具备SayHello接口的能力的变量、
func greet(s SayHello){s.sayHello()//使用Type-Switchswitch tp := s.(type) { //type属于go中的一个关键字,固定写法case Chinese:tp.gongxi()case American:tp.gun()default:fmt.Println("类型断言失败")}
}
func (am American) gun(){fmt.Println("gun之下出真知()")
}func main(){var ch Chinese = Chinese{}var am American = American{}greet(ch) // 你好 恭喜发财greet(am) // hello gun之下出真知()
}

相关文章:

Golang--面向对象

Golang语言面向对象编程说明&#xff1a; Golang也支持面向对象编程(OOP)&#xff0c;但是和传统的面向对象编程有区别&#xff0c;并不是纯粹的面向对象语言。所以我们说Golang支持面向对象编程特性是比较准确的。Golang没有类(class)&#xff0c;Go语言的结构体(struct)和其…...

深度学习经典模型之LeNet-5

1 LeNet-5 1.1 模型介绍 ​ LeNet-5是由 L e C u n LeCun LeCun 提出的一种用于识别手写数字和机器印刷字符的卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09; [ 1 ] ^{[1]} [1]&#xff0c;其命名来源于作者 L e C u n LeCun LeCun的名字…...

Abaqus随机骨料过渡区孔隙三维网格插件:Random Agg ITZ Pore 3D (Mesh)

插件介绍 Random Agg ITZ Pore 3D (Mesh) V1.0 - AbyssFish 插件可在Abaqus内参数化建立包含水泥浆基体、粗细骨料、界面过渡区&#xff08;ITZ&#xff09;、孔隙在内的多相材料混凝土细观背景网格模型。 模型说明 插件采用材料映射单元的方式&#xff0c;将不同相材料赋值…...

PG数据库 jsonb字段 模糊查询

背景&#xff1a; 项目由于多语言的设计&#xff0c;将字段设置成json字段类型&#xff0c;同时存储中文和英文 页面上通过输入框实现模糊的查询 一、表结构&#xff1a;name字段设置jsonb类型 二、表数据 3、Mybatis编写sql select pp.name ->>zh-CN as pmsProductNam…...

javascript-Web APLs (四)

日期对象 用来表示时间的对象 作用&#xff1a;可以得到当前系统时间 在代码中发现了 new 关键字时&#xff0c;一般将这个操作称为 实例化 //创建一个时间对象并获取时间 //获得当前时间 const date new Date() //获得指定时间 const date new Date(2006-6-6) console.log(…...

Keras 3 示例:开启深度学习之旅

Keras 3 示例&#xff1a;开启深度学习之旅 一、Keras 3 简介 Keras 3是一个强大的深度学习框架&#xff0c;它为开发者提供了简洁、高效的方式来构建和训练神经网络。它在之前版本的基础上进行了改进和优化&#xff0c;具有更好的性能、兼容性和功能扩展性。无论是初学者还是…...

鸿蒙Next如何接入微信支付

大家好&#xff0c;这是我工作中接触到的鸿蒙Next接入微信支付&#xff0c;有使用到&#xff0c;分享给大家&#xff0c;轻松便捷 前提:你已有鸿蒙版本的微信&#xff0c;并且微信余额或绑定银行卡有钱&#xff0c;因为内测的微信暂不支持收红包和转账&#xff0c;2.你的应用已…...

nginx(五):关于location匹配规则那些事

关于location匹配规则那些事 1 概述2 语法3 匹配规则说明3.1 精确匹配3.2 前缀匹配&#xff08;^~&#xff09;3.3 正则表达式匹配&#xff08;\~和\~*&#xff09;3.4 普通前缀匹配 4 匹配优先级5 注意事项6 总结 大家好&#xff0c;我是欧阳方超&#xff0c;可以我的公众号“…...

【论文阅读】Associative Alignment for Few-shot Image Classification

用于小样本图像分类的关联对齐 引用&#xff1a;Afrasiyabi A, Lalonde J F, Gagn C. Associative alignment for few-shot image classification[C]//Computer Vision–ECCV 2020: 16th European Conference, Glasgow, UK, August 23–28, 2020, Proceedings, Part V 16. Spri…...

acmessl.cn提供接口API方式申请免费ssl证书

目录 一、前沿 二、API接口文档 1、证书可申请列表 简要描述 请求URL 请求方式 返回参数说明 备注 2、证书申请 简要描述 请求URL 请求方式 业务参数 返回示例 返回参数说明 备注 3、证书查询 简要描述 请求URL 请求方式 业务参数 返回参数说明 备注 4、证…...

DBeaver如何快速格式化sql语句,真简单!

前言 我之前在使用DBeaver的时候&#xff0c;一直不知道其可以格式化sql语句&#xff0c;导致sql语句看起来比较杂乱&#xff0c;今天就来介绍下DBeaver如何格式化sql语句。 如何格式化sql语句 首先&#xff0c;我们打开一个sql窗口&#xff0c;在里面输入我们要查询的sql语…...

OpenCV C++ 计算两幅图像之间的多尺度结构相似性(MSSIM)

目录 一、定义与背景 二、计算流程 三、性质与特点 四、应用场景 五、代码实现 多尺度结构相似性(MSSIM)是一种用于衡量两幅图像之间相似度的指标,它基于结构相似性(SSIM)指数进行扩展,通过在不同尺度上计算SSIM来评估图像的整体质量。以下是对MSSIM的详细介…...

代码随想录第二十二天

回溯算法理论介绍 回溯算法是一种基于递归思想的算法设计技术&#xff0c;适用于解决需要构造所有解或找到特定解的组合问题。回溯的基本思路是通过系统地搜索所有可能的解决方案&#xff0c;然后逐步撤销不符合要求的选择&#xff0c;回到上一步继续尝试。这种算法最适合应用…...

【k8s】ClusterIP能http访问,但是不能ping 的原因

ClusterIP 服务在 Kubernetes 中是可以访问的&#xff0c;但通常无法通过 ping 命令来测试连通性。这主要是因为 ClusterIP 是一个虚拟 IP 地址&#xff0c;而不是实际分配给某个网络接口的 IP 地址。以下是一些原因和解释&#xff1a; 1. 虚拟 IP 地址 ClusterIP 是一个虚拟…...

【力扣打卡系列】单调栈

坚持按题型打卡&刷&梳理力扣算法题系列&#xff0c;语言为go&#xff0c;Day20 单调栈 题目描述 解题思路 单调栈 后进先出 记录的数据加在最上面丢掉数据也先从最上面开始 单调性 记录t[i]之前会先把所有小于等于t[i]的数据丢掉&#xff0c;不可能出现上面大下面小的…...

使用docker安装zlmediakit服务(zlm)

zlmediakit安装 zlmediakit安装需要依赖环境和系统配置&#xff0c;所以采用docker的方式来安装不容易出错。 docker pull拉取镜像(最新) docker pull zlmediakit/zlmediakit:master然后先运行起来 sudo docker run -d -p 1935:1935 -p 80:80 -p 8554:554 -p 10000:10000 -p …...

SOLID原则-单一职责原则

转载请注明出处:https://blog.csdn.net/dmk877/article/details/143447010 作为一名资深程序员越来越感觉到基础知识的重要性&#xff0c;比如设计原则、设计模式、算法等&#xff0c;这些知识的长期积累会让你突破瓶颈实现质的飞跃。鉴于此我决定写一系列与此相关的博客&…...

Transformer究竟是什么?预训练又指什么?BERT

目录 Transformer究竟是什么? 预训练又指什么? BERT的影响力 Transformer究竟是什么? Transformer是一种基于自注意力机制(Self-Attention Mechanism)的神经网络架构,它最初是为解决机器翻译等序列到序列(Seq2Seq)任务而设计的。与传统的循环神经网络(RNN)或卷…...

Jdbc批处理功能和MybatisPlus

文章目录 1. 序言2. JDBC批处理功能和rewriteBatchedStatements3. JDBC批量插入的测试4. MybatisPlus#ServiceImpl.saveBatch()5. 结语&#xff1a;如果对大家有帮助&#xff0c;请点赞支持。如果有问题随时在评论中指出&#xff0c;感谢。 1. 序言 MybatisPlus的ServiceImpl类…...

对于相对速度的重新理解

狭义相对论速度合成公式如下&#xff0c; 现在让我们尝试用另一种方式把它推导出来。 我们先看速度的定义&#xff0c; 常规的速度合成方式如下&#xff0c; 如果我们用速度的倒数来理解速度&#xff0c; 原来的两个相对速度合成&#xff0c; 是因为假定了时间单位是一样的&am…...

Scala的属性访问权限(一)默认访问权限

//eg:银行账户存钱取钱 // 账户类&#xff1a; // -balance() 余额 // -deposit() 存钱 // -withdraw() 取钱 // -transfer(to:账户,amount:Dobule)转账 package Test1104 //银行账户class BankAccount(private var balance:Int){def showMoney():Unit {println(s"…...

【算法】(Python)贪心算法

贪心算法&#xff1a; 又称贪婪算法&#xff0c;greedy algorithm。贪心地追求局部最优解&#xff0c;即每一步当前状态下最优选择。试图通过各局部最优解达到最终全局最优解。但不从整体最优上考虑&#xff0c;不一定全局最优解。步骤&#xff1a;从初始状态拆分成一步一步的…...

条件logistic回归原理及案例分析

前面介绍的二元、多分类、有序Logistic回归都属于非条件Logistic回归&#xff0c;每个个案均是相互独立关系。在实际研究中&#xff0c;还有另外一种情况&#xff0c;即个案间存在配对关系&#xff0c;比如医学研究中配对设计的病例对照研究&#xff0c;此时违反了个案相互独立…...

redis7学习笔记

文章目录 1. 简介1.1 功能介绍1.1.1 分布式缓存1.1.2 内存存储和持久化(RDBAOF)1.1.3 高可用架构搭配1.1.4 缓存穿透、击穿、雪崩1.1.5 分布式锁1.1.6 队列 1.2 数据类型StringListHashSetZSetGEOHyperLogLogBitmapBitfieldStream 2. 命令2.1 通用命令copydeldumpexistsexpire …...

重学Android:自定义View基础(一)

前言 作为一名安卓开发&#xff0c;也被称为大前端&#xff0c;做一个美观的界面&#xff0c;是我们必备的基础技能&#xff0c;可能在开发中我们最常用的是系统自带的View&#xff0c;因为他能满足绝大部分需求&#xff0c;难一点的我们也可以上Github上找个三方库使用&#…...

前端好用的网站分享——CSS(持续更新中)

1.CSS Scan 点击进入CSS Scan CSS盒子阴影大全 2.渐变背景 点击进入color.oulu 3.CSS简化压缩 点击进入toptal 4.CSS可视化 点击进入CSS可视化 这个强推&#xff0c;话不多说&#xff0c;看图! 5.Marko 点击进入Marko 有很多按钮样式 6.getwaves 点击进入getwaves 生…...

华为HarmonyOS借助AR引擎帮助应用实现虚拟与现实交互的能力3-获取设备位姿

设备位姿描述了物体在真实世界中的位置和朝向。AR Engine提供了世界坐标下6自由度&#xff08;6DoF&#xff09;的位姿计算&#xff0c;包括物体的位置&#xff08;沿x、y、z轴方向位移&#xff09;和朝向&#xff08;绕x、y、z轴旋转&#xff09;。通过AR Engine&#xff0c;您…...

qt QColorDialog详解

1、概述 QColorDialog是Qt框架中的一个对话框类&#xff0c;专门用于让用户选择颜色。它提供了一个标准的颜色选择界面&#xff0c;其中包括基本的颜色选择器&#xff08;如调色板和颜色轮&#xff09;、自定义颜色输入区域以及预定义颜色列表。QColorDialog支持RGB、HSV和十六…...

【测试小白--如何写好测试用例--测试用例编写的方法+结合常见登录模块为实例--保姆级教学】

测试用例编写方法&登录模块实例 一、测试用例编写方法1. 等价类划分2. 边界值分析3. 状态转换测试4. 决策表测试5. 错误推测6. 用户场景测试7. 安全测试用例 二、登录模块测试用例实例1. 等价类划分2. 边界值分析3. 状态转换测试4. 决策表测试5. 错误推测6. 用户场景测试7.…...

真题--数组循环题目

1.逆序数表达数组2.用数组表示费波纳希数列3.用数组排序4.二维数组转置5.找到二维数组其中的最大数值6.输出字符数组7.字符数组输出菱形图案8.输入一行字符&#xff0c;统计有多少单词9.有三个字符串&#xff0c;找到最大字符串 1.逆序数表达数组 #include<stdio.h> int…...