go 结构体 - 值类型、引用类型 - 结构体转json类型 - 指针类型的种类 - 结构体方法 - 继承 - 多态(interface接口) - 练习

目录

一、结构体

1、python 与 go面向对象的实现:

2、初用GO中的结构体:(实例化一个值类型的数据(结构体))

输出结果不同的三种方式 

3、实例化一个引用类型的数据(结构体)

4、引用类型(指针类型) vs 值类型(两者的区别)

引用类型(指针类型) - 值类型内存拓扑图:

5、结构体匿名字段、匿名结构体

6、结构体的嵌套

7、结构体转json类型

二、指针类型的种类(结构体指针、数据变量指针、指针数组、数组指针)

三、结构体方法(普通方法、指针方法)

四、结构体继承:

五、结构体多态:(interface接口的运用)

1、空接口的定义:

2、接口如何实现自定义error呢?

1、练习:判断Role(角色)是否存活

2、练习:实现发邮件功能

3、练习:定义标准化返回(json格式)


一、结构体

结构体(Struct)是一种在Go语言中用于定义复合数据类型的机制。它允许你将不同类型的数据组合在一起,形成一个自定义的数据类型,以便更方便地管理和操作相关数据。

在Go语言中,通过type关键字和字段列表来定义结构体。每个字段都可以有自己的数据类型,类似于其他编程语言中的类的成员变量。结构体中的字段可以包含任意类型的数据,包括基本数据类型(如整数、浮点数、字符串等)和其他自定义类型(如其他结构体、数组、切片等)。

结构体中可以定义多个字段,类似于python中class类的属性

以下是一个简单的例子来说明如何定义和使用结构体:

package main

import "fmt"

// 定义一个Person结构体
type Person struct {
    Name string
    Age  int
}

func main() {
    // 创建一个Person类型的变量
    var person1 Person

    // 设置person1的字段值
    person1.Name = "Alice"
    person1.Age = 30

    // 打印person1的字段值
    fmt.Println(person1) // 输出:{Alice 30}

    // 创建并初始化Person结构体的另一个变量
    person2 := Person{
        Name: "Bob",
        Age:  25,
    }

    // 打印person2的字段值
    fmt.Println(person2) // 输出:{Bob 25}
}

在上述示例中,我们通过type关键字定义了一个名为Person的结构体。该结构体有两个字段,分别为NameAge,分别用来存储人的姓名和年龄。

main函数中,我们创建了两个Person类型的变量person1person2,并分别设置了它们的字段值。可以通过运算符来访问结构体变量的字段。

1、python 与 go面向对象的实现:

python 支持面向对象的  --》 class 类

go        不支持面向对象编程,可以使用结构体来实现类似的功能

  python => 面向对象
  class Student(object):
      def __init__(self, id, name, age):
           self.id = id
           ....

  go => 支持结构体
type struct_name struct{
	field_name1 field_type
	field_name2 field_type
	field_name3 field_type
	...
}

2、初用GO中的结构体:(实例化一个值类型的数据(结构体))

// 定义一个Student结构体
type Student struct {
	id int
	name string
	age uint
	school string
}

func main(){
    // 实例化一:实例化一个值类型的数据(结构体)
	// 实例化的时候,可以只初始化部分数据
	zrp := Student{
		id:     1,
		name:   "zrp",
	}
    //输出结果不同的三种方式
	fmt.Printf("%v\n", zrp)
	fmt.Printf("%+v\n", zrp)
	fmt.Printf("%#v\n", zrp)

    // 初始化的时候,如果不指定字段名,就需要每个字段都赋值
    // 否则会报错:too few values in Student{…}
    wbw :=Student{2,"wbw",20, "nongda"}
    // 值类型的数据要看地址的话,需要加&
	fmt.Printf("%#v,地址:%p\n", wbw, &wbw)

}

输出:
{1 zrp 0 }
{id:1 name:zrp age:0 school:}
main.Student{id:1, name:"zrp", age:0x0, school:""}
main.Student{id:2, name:"wbw", age:0x14, school:"nongda"},地址:0xc000100540

输出结果不同的三种方式 

fmt.Printf("%v\n", zrp)
fmt.Printf("%+v\n", zrp)
fmt.Printf("%#v\n", zrp)

输出:

{1 zrp 0 }
{id:1 name:zrp age:0 school:}
main.Student{id:1, name:"zrp", age:0x0, school:""}

3、实例化一个引用类型的数据(结构体)

package main

import "fmt"

// 定义一个Student结构体
type Student struct {
	id int
	name string
	age uint
	school string
}

func main(){

	// 实例化一个引用类型
	// 使用new实例化开辟一片内存空间,创建一个实例对象,返回这个对象的内存地址
	mq := new(Student)   //使用new实例化开辟一片内存空间 , mq是引用类型的数据
	mq.id = 3            //
	mq.name = "mq"
	mq.age = 18
	fmt.Printf("%#v,地址:%p\n", mq, mq)
}

输出:
&main.Student{id:3, name:"mq", age:0x12, school:""},0xc00000a028

4、引用类型(指针类型) vs 值类型(两者的区别)

package main

import "fmt"

// 定义一个Student结构体
type Student struct {
	id int
	name string
	age uint
	school string
}

func main(){
    // 实例化一个值类型的数据
    wbw :=Student{2,"wbw",20, "nongda"}

    // 实例化一个引用类型的数据
	mq := new(Student)
	mq.id = 3
	mq.name = "mq"
	mq.age = 18

    // 引用类型(指针类型) vs 值类型 区别

	// 引用类型 => 指向了一个内存数据,注意:如果要修改的话,一同变化
	mq2 := mq
	mq2.name = "米强"
	fmt.Printf("type:%T,values:%+v,address:%p\n",mq, mq,mq)
	fmt.Printf("type:%T,values:%+v,address:%p\n",mq2, mq2,mq2)
	// 值类型:两份数据,相互不影响
	wbw2 := wbw
	wbw2.name = "王百文"
	fmt.Printf("type:%T,values:%+v,address:%p\n",wbw, wbw, &wbw)
	fmt.Printf("type:%T,values:%+v,address:%p\n",wbw2, wbw2,&wbw2)
}

输出:
type:*main.Student,values:&{id:3 name:米强 age:18 school:},address:0xc0001004e0
type:*main.Student,values:&{id:3 name:米强 age:18 school:},address:0xc0001004e0
type:main.Student,values:{id:2 name:wbw age:20 school:nongda},address:0xc0001004b0
type:main.Student,values:{id:2 name:王百文 age:20 school:nongda},address:0xc000100570

引用类型(指针类型) - 值类型内存拓扑图:

5、结构体匿名字段、匿名结构体

package main

import "fmt"

// 结构体匿名字段 => 如果没有定义字段名,会用类型的名字直接充当字段名
type Stu struct {
	string
	int
}

func main(){
	// 结构体匿名字段实例化
	st1 := Stu{"abc", 100}
	fmt.Printf("st1:%+v\n", st1)

    // 匿名结构体: 适合一次性使用
	stu2 := struct {
		name string
		age int
	}{"cali", 30}
	fmt.Printf("st2:%+v\n", stu2)
}

输出:
st1:{string:abc int:100}
st2:{name:cali age:30}

6、结构体的嵌套

package main

import "fmt"

// 结构体的嵌套
type Book struct {
	title string
	Author struct{
		name, tel string
		age int
	}
}

func main(){

	// 嵌套结构体的实例化
	b1 := Book{title: "GO从入门到精通"}
	b1.Author.name = "cici"
	b1.Author.tel = "186xxxxxxxx"
	fmt.Printf("b1:%+v\n", b1)
}

输出:
b1:{title:GO从入门到精通 Author:{name:cici tel:186xxxxxxxx age:0}}

7、结构体转json类型

package main

import (
	"encoding/json"
	"fmt"
)

// Web开发,数据定义都是结构体类型 结构体数据 <=> json <=>前端
// 加Tag(两个反引号``): Tag加上json配置项:他当将结构体转换成json的时候读取该配置
// Student结构体内的数据转换为json格式
type Student struct{
    // 转换json格式
	Id int			`json:"id"`
	Name string		`json:"username"`

	// 设置成“-” => 表示忽略该字段
	School string	`json:"-"`

	// 如果没有配置 => 使用默认字段名
	School2 string

	// omitempty如果当前字段School3有值的,会显示出来,如果没有值就不会显示
	School3 string 	`json:"school,omitempty"`
}

// 使用json模块
// go结构体数据 <=> json <=>前端
func main(){
    // 实例化
	s1 := Student{
		Id:     1,
		Name:   "user1",
		School: "nongda",
		School3: "nongda3",  // omitempty会导致如果School3没有值就不会显示School3字段
	}
    // 用于进行go的异常处理
	bmarshal, err := json.Marshal(s1)
	if err == nil {
        // 输出转换后的json格式数据
		fmt.Println(string(bmarshal))
	}else{
        // 输出其中的错误
		fmt.Println("err:", err)
	}
}

输出:
{"id":1,"username":"user1","School2":"","school":"nongda2"}

二、指针类型的种类(结构体指针、数据变量指针、指针数组、数组指针)

package main

import "fmt"

// 定义一个Student结构体
type Student struct {
	id int
	name string
	age uint
	school string
}

func main(){
	// 结构体指针
	mc := &Student{
		id: 4,
		name: "mc",
	}
	fmt.Printf("type:%T, values:%+v\n", mc, mc)

	// 结构体指针中,可以使用简化的语法
	fmt.Printf("%+v, %s\n", mc, (*mc).name)
	fmt.Printf("%+v, %s\n", mc, mc.name)

	// 数据变量指针获取数据的方法
	var n1 *int  // 定义n1为int指针
	n2 := 10     // 给n2赋值
	n1 = &n2     // 将n2的地址传给n1指针
	*n1 = 20     // 给n1指针赋值为20
	fmt.Printf("type:%T,address:%p, value:%d\n",n1, n1, *n1)
	fmt.Printf("address:%p, value:%d\n",&n2, n2)

    // 指针数组 parr是一个数组,有4个元素,每个元素都是一个int类型的指针
    var parr [4]*int
	a := 10
	parr[2] = &a
	fmt.Printf("value:%v, address:%v\n", *parr[2], parr[2])

    // 数组指针:是一个指针,指向了一个数组类型的数据(访问数据的时候,可以使用简化方式)
    var parr2 *[4]int
	arr := [4]int{1,2,3,4}
	parr2 = &arr
	fmt.Printf("arrvalue:%v, value:%v, value:%v\n", parr2, (*parr2)[0], parr2[0])
}

输出:
type:*main.Student, values:&{id:4 name:mc age:0 school:}
type:*int,address:0xc0000a60a0, value:20
address:0xc0000a60a0, value:20
&{id:4 name:mc age:0 school:}, mc
&{id:4 name:mc age:0 school:}, mc
value:10, address:0xc00000e138
arrvalue:&[1 2 3 4], value:1, value:1

三、结构体方法(普通方法、指针方法)

package main

import "fmt"
// 结构体方法的实现
// 在普通函数前加上一个接收者(receiver)
// func (s receiverType) funcName(args...)  --》 结构体方法的定义

// 定义一个Student结构体
type Student struct {
	id int
	name string
	age uint
	school string
}

// 为Student结构绑定一个changeSchool方法 (值类型的结构体,在函数内部修改数据并不会影响函数外面)
func (s Student) changeSchool(school string){
	s.school = school
}

// 为*Student(指针)结构体绑定一个changeSchool2方法 (指针类型的结构体,在函数中修改了数据会影响外部的数据)
func (s *Student) changeSchool2(school string){
	s.school = school
}

// 因此我们在调用结构体方法的时候,需要注意是什么结构体类型
func main(){
	// 实例化一个值类型的数据
	// 实例化一个结构体
	// 实例化的时候,可以只初始化部分数据
	zrp := Student{
		id:     1,
		name:   "zrp",
	} 

    // 结构体指针
	mc := &Student{
		id: 4,
		name: "mc",
	}

    // 使用结构体方法
    // 值结构(普通结构体)
	// 普通结构:外面的数据和函数中的数据是两个不同的数据,在函数内修改,不影响函数外
	zrp.changeSchool("湖南农业大学")
	fmt.Printf("新学校是:%v\n", zrp.school)
    // 输出为:新学校是: (没有传入值)

    // 指针结构体:外面和函数中是同一个数据,在函数中修改了,影响函数外
	mc.changeSchool2("湖南农业大学")
	fmt.Printf("新学校是:%v\n", mc.school)

}

输出:
新学校是:
新学校是:湖南农业大学

四、结构体继承:

package main

import "fmt"

// 创建Author作者结构体
type Author struct{
    // 定义字段
	name, tel string
	age int
}

// 继承:Book继承了Author结构体
type Book struct {
	title string
	author Author
}

// 给Book添加了一个结构体方法
func (b *Book) Print(){  
	fmt.Printf("%s的作者是:%s\n", b.title, b.author.name)
}

func main(){
	// 实例化方法
    // 先实例化Book,在将Author继承给Book
	b1 := Book{title: "《Go入门到精通》"}
	b1.author.name = "TeacherWen"
	b1.author.tel = "187xxxxxxx"
	fmt.Printf("%+v\n",b1)
	b1.Print()

	// 先实例化Author, 再把Author赋值给Book
	a1 := Author{name: "TeacherFeng"}
	b2 := Book{title: "《Docker从入门到精通》", author: a1}
	fmt.Printf("%+v\n",b2)
	b2.Print()
}

输出:
{title:《Go入门到精通》 author:{name:TeacherWen tel:187xxxxxxx age:0}}
《Go入门到精通》的作者是:TeacherWen
{title:《Docker从入门到精通》 author:{name:TeacherFeng tel: age:0}}
《Docker从入门到精通》的作者是:TeacherFeng

五、结构体多态:(interface接口的运用

多态:一个接口多个形态(为多个不同的数据类型提供统一的接口)
        其实就是一个功能,展现多种形态
        多态是指同一种操作或方法可以在不同的对象上产生不同的行为。

Go语言中实现多态需要用到interface

Interface接口类型可以定义一组方法(而非变量),并且不需要实现


// 定义一个函数MyPrint,我们可以通过MyPrint来使多个数据进行打印操作,但是当前MyPrint并不是多态的,需要下面的interface接口操作
// func MyPrint(s string){
// 	 fmt.Println("")
// }


// 如果WePay结构体实现了PayInterface接口所有的方法,那么可以说
// WePay结构是是PayInterface类型
type PayInterface interface {
	// 声明一些方法,但不需要实现
	// 方法名(参数列表) 返回值 --》pay()就为方法接口,他没有参数和返回值
	pay()
    // 可以定义多个方法接口
    // pay2()、

    // print()
    // 运行print()方法后报错:AliPay does not implement PayInterface (missing print method) 和 WePay does not implement PayInterface (missing print method)
    // 说明AliPay 和 WePay 没有实现print() 方法
    // 如果说WePay结构体和AliPay结构体实现了PayInterface接口所有的方法,那么可以说这个结构体是PayInterface的可以实现的接口类型。

// 下面我们将要实现微信支付和支付宝支付操作

// 定义微信支付结构体
type WePay struct {
	name string
}

// WePay实现了pay方法 等于  WePay实现PayInterface接口(wepay可以看作是PayInterface类型(上面定义的interface接口类型结构体))
func (w WePay) pay(){
	fmt.Printf("This is WePay:%s\n", w.name)
}

// 定义支付宝支付结构体
type  AliPay struct {
	name string
}

// AliPay实现PayInterface接口
func (a AliPay) pay(){
	fmt.Printf("This is AliPay:%s\n", a.name)
}

// 定义函数payment用于实现PayInterface接口的pay()方法
func payment(p PayInterface){
	p.pay()
}

func main(){
    // 实例化w1 和 a1,分别用于微信支付和支付宝支付
	w1 := WePay{name: "cici"}
	a1 := AliPay{name: "aiai"}
    // 调用payment函数传入实例,实现WePay和AliPay 
	payment(w1)
	payment(a1)
}

输出:
This is WePay:cici
This is AliPay:aiai

1、空接口的定义:

空接口可以表示任意类型的值。空接口的作用在于可以在不确定类型的情况下,用于保存和传递各种不同类型的值。由于空接口可以表示任意类型的值,所以它在某些场景下非常有用,比如在函数参数中,可以接受不同类型的参数,或者在数据结构中,可以存储不同类型的元素。

package main

import "fmt"

// 空接口
type Empty interface {}

// 该test函数可以接收任意类型的数据,空接口的定义方式
func test(f interface{}){
	fmt.Printf("%v\n",f)
}

func main(){
	// 空接口的使用
	// 该实例希望它的方法是string类型,但是它的value值可以是任意类型的,如希望m1定义为:m1 = {"name":"cici", "age":20}这种value可以是任意类型的,因此我们可以定义一个空接口Empty interface
	// Empty结构体定义方式
	m1 :=map[string]Empty{
		"name":"cici",
		"age": 20,
	}

	//interface{}方法定义方式
	m2 :=map[string]interface{}{
		"name":"aiai",
		"age": "18",
	}
	fmt.Printf("%v\n%v\n", m1, m2)
}

输出:
map[age:20 name:cici]
map[age:18 name:aiai]

2、接口如何实现自定义error呢?

package main

import (

	"fmt"
    //"errors"
)

// 定义NameCheck函数,用于返回Error使用
// 如果name值为空,返回一个错误,否则就返回nil
func NameCheck(name string) error {  // 返回数据的类型是error类型
	if name == ""{
		// return errors.New("名字不能为空") // 通过errors包内New函数来进行error的提示, 比较复杂
		// 输出为:名字不能为空

		// 进行自定义错误(优点是比errors包内调用New方法简单快捷很多)
		return NameEmptyError{msg:"名字不能为空", code:1001}
		// 输出为:出错了:名字不能为空
	}
	return nil
}

// 自定义错误 => 给NameEmptyError实现一个Error方法,它就是一个error类型了
type NameEmptyError struct {
	msg string
	code int
}

// 定义NameEmptyError结构体方法Error()
func (e NameEmptyError) Error() string{
	// e.msg表示错误的信息
	return "出错了:"+e.msg
}

func main(){
	// 定义变量name
	name := ""

	// 调用NameCheck函数
	err := NameCheck(name)
	if err != nil{
		// 出现错误,输出错误
		fmt.Println(err)
	}else{
		fmt.Println(name)
	}
}

1、练习:判断Role(角色)是否存活

定义Role(角色) => 属性:name, blood, isAlive(是否存活)

                       isAlive => 判断blood是<=0 True or False

package main

import "fmt"

// 定义结构体
type Role struct {
	name string
	blood int
}

// 非指针型的绑定(将r 绑定为 Role 结构体) isAlive() 是一个函数
func (r Role) isAlive() bool{
	if r.blood <= 0{
		return false
	}else{
		return true
	}
}

// 指针型的绑定
//func (r *Role) isAlive() bool {
//	if r.blood <= 0{
//		return false
//	}else{
//		return true
//	}
//}

func main(){
	// 创建实例类型
	role1 := Role{"role1", 90}
	role2 := Role{"role2", 0}
	// 打印数据
	fmt.Printf("%s:%v\n", role1.name, role1.isAlive())
	fmt.Printf("%s:%v\n", role2.name, role2.isAlive())
}

输出:
role1:true
role2:false

2、练习:实现发邮件功能

功能介绍:

普通用户:结构体User => 字段:username, email, ShowUserInfo(), SendMail()

Root用户:结构体Root => 字段:username, email, ShowSysInfo(), SendMail()

邮件告警的功能 => sendNotification函数 --》可以接受所有权限用户

普通用户User和Root用户都能够使用sendNotification函数 => 并实现对对象的SendMail()

package main

import "fmt"

// 定义User结构体,内存字段username(用户名)、email(邮件地址)
type User struct {
	username string
	email string
}

// 定义Root结构体,内存字段username(用户名)、email(邮件地址)
type Root struct {
	username string
	email string
}

// 定义ShowUserInfo()结构体方法,调用User结构体,实现展示用户信息的功能
func (u User) ShowUserInfo(){
	fmt.Println("这是User的userInfo, User为:", u.username)
}

// 定义SendMail()结构体方法,调用User结构体,实现发送用户邮件的功能
func (u User) SendMail(){
	fmt.Printf("User:%s正在发送邮件到%s\n", u.username, u.email)
}

// 定义ShowSysInfo()结构体方法,调用Root结构体,实现展示Root信息的功能
func (r Root) ShowSysInfo(){
	fmt.Println("这是Root的sysInfo, Root为:", r.username)
}

// 定义SendMail()结构体方法,调用Root结构体,实现Root发送邮件的功能
func (r Root) SendMail(){
	fmt.Printf("Root:%s正在发送邮件到%s\n", r.username, r.email)
}

// 定义SendMailInterface结构体,内存SendMail()结构体方法
type SendMailInterface interface {
	SendMail()
}

// 定义sendNotification函数,作用是接收参数并作为SendMail的对象
func sendNotification(s SendMailInterface){
	s.SendMail()
}


func main()  {
	// 结构体实例化
	r := Root{username: "root", email: "root@sc.com"}
	u := User{username: "user1", email: "user1@sc.com"}
	// 调用sendNotification函数,并传入实例参数
	r.ShowSysInfo()
	sendNotification(r)
	u.ShowUserInfo()
	sendNotification(u)
}

输出:
这是Root的sysInfo, Root为: root
Root:root正在发送邮件到root@sc.com
这是User的userInfo, User为: user1
User:user1正在发送邮件到user1@sc.com

3、练习:定义标准化返回(json格式)

package main

/*
// 定义返回的数据格式,将返回的数据用json的方式打印出来
// Code, Message, Data
// s.json() => 将它转换成json格式(string)

后端开发:API => 访问url => 返回数据(无页面) => 访问者
标准化返回:
{
	”code": 1001,
	"message": "参数不完整“,
	"data": {}/[]/other
}
*/

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

时序数据库 TDengine 与 WhaleStudio 完成相互兼容性测试认证

近年来&#xff0c;开源及其价值获得社会各界的广泛认可&#xff0c;无论是国家政策导向还是企业数字化转型&#xff0c;都在加速拥抱开源。对于如操作系统、数据库等基础软件来说&#xff0c;开源更是成为驱动技术创新的有力途径。 在此背景下&#xff0c;近日&#xff0c;涛…

Spring boot开发实用篇

一、热部署 1.启动热部署 1.导入坐标 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId> </dependency> 2.使用构建项目操作启动热部署 3.关于热部署 重启&#xff1a;自定义开发…

2023软考下半年考试和报名时间汇总(附详细报名流程)

2023年上半年软考结束了&#xff0c;相信有不少准备报考下半年软考的考生正摩拳擦掌&#xff0c;期待在11月的考试中大显身手。2023下半年软考什么时候报名呢&#xff1f;一起来看看吧~ 根据中国计算机技术职业资格网发布的关于《2023年度计算机技术与软件专业技术资格&#x…

完美解决PostgresSQL14或15安装后pgAdmin不能打开的问题(亲测有效)

今天安装PostgreSQL的时候遇到一个问题&#xff0c;由于选择的是安装时候自带的pgAdmin 后台如论如何都打不开&#xff0c;一直出现如下界面 一直在此界面&#xff0c;无法进入服务器。 通过修改.js配置&#xff0c;或者是删除C:\Users\PICC\AppData\Roaming\pgadmin目录下所…

SpringBoot复习:(12)SpringApplicationRunListener和 SpringApplicationRunListeners

SpringApplicationRunListener接口定义如下&#xff1a; public interface SpringApplicationRunListener {default void starting() {}default void environmentPrepared(ConfigurableEnvironment environment) {}default void contextPrepared(ConfigurableApplicationConte…

【机器学习】Gradient Descent

Gradient Descent for Linear Regression 1、梯度下降2、梯度下降算法的实现(1) 计算梯度(2) 梯度下降(3) 梯度下降的cost与迭代次数(4) 预测 3、绘图4、学习率 首先导入所需的库&#xff1a; import math, copy import numpy as np import matplotlib.pyplot as plt plt.styl…

什么是多运行时架构?

服务化演进中的问题 自从数年前微服务的概念被提出&#xff0c;到现在基本成了技术架构的标配。微服务的场景下衍生出了对分布式能力的大量需求&#xff1a;各服务之间需要相互协作和通信&#xff0c;以及共享状态等等&#xff0c;因此就有了各种中间件来为业务服务提供这种分…

【雕爷学编程】MicroPython动手做(30)——物联网之Blynk 3

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

面试之多线程案例(四)

1.单例模式 单例模式是指在内存中只会创建且仅创建一次对象的设计模式。在程序中多次使用同一个对象且作用相同时&#xff0c;为了防止频繁地创建对象使得内存飙升&#xff0c;单例模式可以让程序仅在内存中创建一个对象&#xff0c;让所有需要调用的地方都共享这一单例对象。…

振弦采集仪完整链条的岩土工程隧道安全监测

振弦采集仪完整链条的岩土工程隧道安全监测 隧道工程是一种特殊的地下工程&#xff0c;其建设过程及运行期间&#xff0c;都受到各种内外力的作用&#xff0c;如水压、地震、地质变形、交通荷载等&#xff0c;这些因素都会对隧道的安全性产生影响。因此&#xff0c;对隧道的安…

解决项目加载时空白页面

背景&#xff1a;当前端项目加载时&#xff0c;遇到网络不稳定或更新项目时&#xff0c;出现长时间白屏情况&#xff0c;对用户体验非常不友好。 解决方法 CSN加速增加带宽前端页面修改 本文就第三点展开 index.html页面 &#xff08;public文件夹下&#xff09; <!DOCTYPE…

在线餐饮油烟实时监测系统的设计与实现

安科瑞 华楠 摘 要&#xff1a;为了解决传统油烟检测方法中成本高、效率低、实时性差等问题&#xff0c;设计开发了一种在线油烟实时监测系统&#xff1b;系统由采集、通讯、服务器和用户交互四个模块组成&#xff1b;采集模块采集油烟数据&#xff0c;通过GPRS通讯技术将数据发…

Delphi 中High DPI开发注意事项

目录 前言&#xff1a; 什么是High DPI? 一、表现不一致的现象 二、当前的解决方案 三、重点 前言&#xff1a; 什么是High DPI? High DPI&#xff08;高分辨率显示&#xff09;是指显示设备具有高像素密度的特征。它意味着在相同的显示区域内&#xff0c;显示设备能够…

如何⾃定义⼀个SpringBoot Srarter

⾃定义⼀个SpringBoot Srarter 1、创建⼀个项⽬&#xff0c;命名为 demo-springboot-starter&#xff0c;引⼊SpringBoot相关依赖 2、编写配置⽂件 定义属性配置的前缀 3、⾃动装配 创建⾃动配置类HelloPropertiesConfigure 4、配置⾃动类 在 /resources/META-INF/spri…

自监督去噪: self2self 原理及实现(Pytorch)

Self2Self With Dropout: Learning Self-Supervised Denoising From Single Image 文章地址&#xff1a;https://ieeexplore.ieee.org/document/9157420原始代码&#xff1a;https://github.com/scut-mingqinchen/self2self本文参考代码: https://github.com/JinYize/self2self…

【万字长文】SpringBoot整合MyBatis搭建MySQL多数据源完整教程(提供Gitee源码)

前言&#xff1a;在我往期的博客介绍了2种关于如何使用SpringBoot搭建多数据源操作&#xff0c;本期博客我参考的是目前主流的框架&#xff0c;把最后一种整合多数据源的方式以博客的形式讲解完&#xff0c;整合的过程比较传统和复杂&#xff0c;不过我依旧会把每个实体类的思路…

NASA和uAvionix在AAM测试场部署SkyLine C2指挥和控制服务

蒙大拿州比格福克和弗吉尼亚州汉普顿2023年07月28日——美国宇航局和uAvionix签署了一项太空法案协议&#xff0c;为城市环境中的无人机系统 (UAS)开发先进的超视距(BVLOS)指挥和控制(C2)技术。根据协议&#xff0c;NASA将与uAvionix合作&#xff0c;利用基于互联网的基础设施和…

亚马逊云科技与真格基金发起「AI超新星计划」,助力早期创业者快速启动项目

大模型创业热度仍旧在持续增加&#xff0c;“百模大战”中AI创业者们的机会更多是在应用层。为了尽可能降低AI创业者的启动门槛&#xff0c;亚马逊云科技携手头部早期投资机构真格基金共同发起了「AI超新星计划」&#xff0c;为心怀梦想的AI应用创业者们提供了从云资源、模型选…

NSS刷web3

[HDCTF 2023]SearchMaster [天翼杯 2021]esay_eval 这题会匹配A或B类 如 "A":1: 绕不过去 可以考虑快速析构 <?php class A{public $code "";function __call($method,$args){eval($this->code);}function __wakeup(){$this->code "&q…