9、面向对象、泛型与反射

news2024/11/19 9:27:21

目录

  • 一、构造函数
  • 二、继承与重写
  • 三、泛型
  • 四、反射
    • 1 - 反射的基本概念
    • 2 - 反射的基础数据类型
    • 3 - 反射API
        • a - 获取Type类型
        • b - 获取struct成员变量的信息
        • c - 获取struct成员方法的信息
        • d - 获取函数的信息
        • e - 判断类型是否实现了某接口
  • 五、reflect.Value
        • a - 空value判断
        • b - 获取Value
        • c - 指针Value和非指针Value互相转换
        • d - 获取Value对应的原始数据
        • e - 通过Value修改原始数据的值
        • f - 通过Value修改slice
        • g - 通过Value修改map
  • 六、反射创建对象
  • 七、反射调用函数和成员方法

一、构造函数

  • 定义User结构体
type User struct {
	Name string //""表示未知
	Age  int    //-1表示未知
	Sex  byte   //1男,2女,3未知
}

func main() {
	u := User{}     //构造一个空的User,各字段都取相应数据类型的默认值
	up := new(User) //构造一个空的User,并返回其指针
}
  • 自定义构造函数
func NewDefaultUser() *User {
	return &User{
		Name: "",
		Age:  -1,
		Sex:  3,
	}
}

func NewUser(name string, age int, sex byte) *User {
	return &User{
		Name: name,
		Age:  age,
		Sex:  sex,
	}
}
  • 单例模式:确保在并发的情况下,整个进程里只会创建struct的一个实例
type User struct {
	Name string //""表示未知
	Age  int    //-1表示未知
	Sex  byte   //1男,2女,3未知
}

func NewDefaultUser() *User {
	return &User{
		Name: "",
		Age:  -1,
		Sex:  3,
	}
}

var (
	sUser *User
	uOnce sync.Once
)

func GetUserInstance() *User {
	uOnce.Do(func() { //确保即使在并发的情况下,下面的3行代码在整个go进程里只会被执行一次
		if sUser == nil {
			sUser = NewDefaultUser()
		}
	})
	return sUser
}

func main() {
	//调用GetUserInstance()得到的是同一个User实例
	su1 := GetUserInstance()
	su2 := GetUserInstance()
	//修改su1会影响su2
	fmt.Println(su1.Age, su2.Age) //-1 -1
	su1.Age = 20
	fmt.Println(su2.Age) //20
}

二、继承与重写

  • 继承的实现:通过嵌入匿名结构体,变相实现“继承”的功能,因为访问匿名成员时可以跳过成员名直接访问它的内部成员
type Plane struct {
	color string
}
type Bird struct {
	Plane
}

func main() {
	bird := Bird{}
	bird.Plane.color = "red"
	fmt.Println(bird.color) //red
}
  • 重写的实现
type Plane struct {
	color string
}

func (pl Plane) fly() {
	fmt.Println("plane fly")
}

type Bird struct {
	Plane
}

func (bd Bird) fly() {
	fmt.Println("bird fly")
}

func main() {
	bird := Bird{}
	bird.Plane.color = "red"
	fmt.Println(bird.Plane.color) //red
	fmt.Println(bird.color)       //red

	bird.Plane.fly() //plane fly
	bird.fly()       //bird fly
}
  • 组合:严格意义上来说Go语言并不支持继承,它只是支持组合
type Plane struct{}
type Car struct{}

//Bird组合了Plane和Car的功能
type Bird struct {
	Plane
	Car
}

三、泛型

  • 使用泛型之前:在有泛型之前,同样的功能需要为不同的参数类型单独实现一个函数
func add4int(a, b int) int {
	return a + b
}
func add4float32(a, b float32) float32 {
	return a + b
}
func add4string(a, b string) string {
	return a + b
}
  • 使用泛型之后
type Addable interface { //类型约束
	int | string
}

func add[T Addable](a, b T) T {
	return a + b
}

func main() {
	fmt.Println(add(1, 2))             //3
	fmt.Println(add("hello", "world")) //helloworld
}

四、反射

1 - 反射的基本概念

  • 什么是反射:反射就是在运行期间(不是编译期间)探知对象的类型信息和内存结构、更新变量、调用它们的方法
  • 反射的使用场景
    • 函数的参数类型是interface{},需要在运行时对原始类型进行判断,针对不同的类型采取不同的处理方式。比如json.Marshal(v interface{})
    • 在运行时根据某些条件动态决定调用哪个函数,比如根据配置文件执行相应的算子函数
  • 反射的弊端
    • 代码难以阅读,难以维护
    • 编译期间不能发现类型错误,覆盖测试难度很大,有些bug需要到线上运行很长时间才能发现,可能会造成严重用后
    • 反射性能很差,通常比正常代码慢一到两个数量级。在对性能要求很高,或大量反复调用的代码块里建议不要使用反射

2 - 反射的基础数据类型

  • 反射的基础数据类型
    在这里插入图片描述
  • reflect.Type用于获取类型相关的信息
type Type interface {
	Method(int) Method                                           //第i个方法
	MethodByName(string) (Method, bool)                          //根据名称获取方法
	NumMethod() int                                              //方法的个数
	Name() string                                                //获取结构体名称
	PkgPath() string                                             //包路径
	Size() uintptr                                               //占用内存的大小
	String() string                                              //获取字符串表述
	Kind() Kind                                                  //数据类型
	Implements(u Type) bool                                      //判断是否实现了某接口
	AssignableTo(u Type) bool                                    //能否赋给另外一种类型
	ConvertibleTo(u Type) bool                                   //能否转换为另外一种类型
	Elem() Type                                                  //解析指针
	Field(i int) StructField                                     //第i个成员
	FieldByIndex(index []int) StructField                        //根据index路径获取嵌套成员
	FieldByName(name string) (StructField, bool)                 //根据名称获取成员
	FieldByNameFunc(match func(string) bool) (StructField, bool) //根据匹配函数匹配需要的字段
	Len() int                                                    //容器的长度
	NumIn() int                                                  //输出参数的个数
	NumOut() int                                                 //返回参数的个数
}
  • reflect.Value用于修改原始数据类型里的值
type Value struct {
	typ *rtype         // 代表的数据类型
	ptr unsafe.Pointer // 指向原始数据的指针
}

3 - 反射API

a - 获取Type类型


type User struct {
	age    int64
	Gender bool `json:"sex"`
	uint8
}

type Student struct {
	User
}

func get_type() {
	typeI := reflect.TypeOf(2)
	typeS := reflect.TypeOf("abc")
	fmt.Println(typeI)                          //int -> reflect.Type
	fmt.Printf("%s %T\n", typeI, typeI)         //int *reflect.rtype
	fmt.Println(typeI.String())                 //int -> string
	fmt.Println(typeS)                          //string -> reflect.Type
	fmt.Println(typeI.Kind() == reflect.Int)    //true -> reflect.Kind
	fmt.Println(typeS.Kind() == reflect.String) //true -> reflect.Kind
	fmt.Println("-------------------")
	
	user := &User{}
	typeUser := reflect.TypeOf(user)
	fmt.Println(typeUser)                                 //*main.User
	fmt.Println(typeUser.Elem())                          //main.User
	fmt.Println(typeUser.Elem().Name())                   //User
	fmt.Println(typeUser.Kind() == reflect.Ptr)           //true -> ptr
	fmt.Println(typeUser.Elem().Kind() == reflect.Struct) //true -> struct
	fmt.Println("-------------------")
	
	user2 := &User{}
	typeUser2 := reflect.TypeOf(user2)
	fmt.Println(typeUser2.Size())
	fmt.Println(typeUser2.PkgPath())
}

b - 获取struct成员变量的信息

type User struct {
	age    int64
	Gender bool `json:"sex"`
	uint8
}

type Student struct {
	Name string
	user User
}

func get_field() {
	typeUser := reflect.TypeOf(User{}) //需要用struct的Type,不能用指针的Type
	fieldNum := typeUser.NumField()    //成员变量的个数
	for i := 0; i < fieldNum; i++ {
		field := typeUser.Field(i)
		fmt.Println(field.Name)            //变量名称
		fmt.Println(field.Offset)          //相对于结构体首地址的内存偏移量,string类型会占据16个字节
		fmt.Println(field.Anonymous)       //是否为匿名成员
		fmt.Println(field.Type)            //数据类型,reflect.Type类型
		fmt.Println(field.IsExported())    //包外是否可见(即是否以大写字母开头)
		fmt.Println(field.Tag.Get("json")) //获取成员变量后面``里面定义的tag
		fmt.Println("------------------")
	}

	//获取指定成员变量的信息
	if field, ok := typeUser.FieldByName("Gender"); ok {
		fmt.Println(field.Name)            //Gender
		fmt.Println(field.Offset)          //8
		fmt.Println(field.Anonymous)       //false
		fmt.Println(field.Type)            //bool
		fmt.Println(field.IsExported())    //true
		fmt.Println(field.Tag.Get("json")) //sex
		fmt.Println("------------------")
	} else {
		fmt.Println("结构体中没有名为Gender的成员变量")
	}

	//根据index获取成员变量信息
	field := typeUser.FieldByIndex([]int{0}) //使用切片可以兼容嵌套
	fmt.Println(field.Name)                  //age
	fmt.Println(field.Offset)                //0
	fmt.Println(field.Anonymous)             //false
	fmt.Println(field.Type)                  //int64
	fmt.Println(field.IsExported())          //false
	fmt.Println(field.Tag.Get("json"))
	fmt.Println("------------------")

	//使用切片可以兼容嵌套
	typeStudent := reflect.TypeOf(Student{})
	fieldUser := typeStudent.FieldByIndex([]int{1, 0})
	fmt.Println(fieldUser.Name) //age
}

c - 获取struct成员方法的信息

type User struct {
	age    int64
	Gender bool `json:"sex"`
	uint8
}

type Student struct {
	Name string
	user User
}

func (*Student) Examine1(a int, b float32) (byte, string) {
	return byte(3), "abc"
}

func (Student) Examine2(a int, b float32) (byte, string) {
	return byte(3), "abc"
}

func get_method_info() {
	typeStudent := reflect.TypeOf(Student{})
	foreachMethod(typeStudent) //Examine2 -> 不会取到指针的方法

	ptypeStudent := reflect.TypeOf(&Student{})
	foreachMethod(ptypeStudent) //Examine1 //Examine2 -> Examine2也属于指针的方法

	//根据名称获取
	if method, ok := typeStudent.MethodByName("Examine2"); ok {
		fmt.Println(method.Name)
		fmt.Println(method.Type)
		fmt.Println(method.IsExported())
		fmt.Println(method.Type.NumIn())
		fmt.Println(method.Type.NumOut())
	}
}

func foreachMethod(rt reflect.Type) {
	methodNum := rt.NumMethod()
	for i := 0; i < methodNum; i++ {
		method := rt.Method(i)
		fmt.Println(method.Name)
		fmt.Println(method.Type)
		fmt.Println(method.IsExported())
		fmt.Println(method.Type.NumIn())
		fmt.Println(method.Type.NumOut())
		fmt.Println("-------------")
	}
}

d - 获取函数的信息

func Add(a, b int) int {
	return a + b
}

func main() {
	addType := reflect.TypeOf(Add)
	fmt.Printf("is function type %t\n", addType.Kind() == reflect.Func) //true
	argInNum := addType.NumIn()                                         //输入参数的个数
	argOutNum := addType.NumOut()                                       //输出参数的个数
	for i := 0; i < argInNum; i++ {
		argTyp := addType.In(i)
		fmt.Printf("第%d个输入参数的类型%s\n", i, argTyp)
	}
	for i := 0; i < argOutNum; i++ {
		argTyp := addType.Out(i)
		fmt.Printf("第%d个输出参数的类型%s\n", i, argTyp)
	}
}

e - 判断类型是否实现了某接口

type People interface {
	Examine1(a int, b float32) (byte, string)
}

type User struct {
	age    int64
	Gender bool `json:"sex"`
	uint8
}

type Student struct {
	Name string
	user User
}

func (*Student) Examine1(a int, b float32) (byte, string) {
	return byte(3), "abc"
}

func convert() {
	userType := reflect.TypeOf(User{})
	studentType := reflect.TypeOf(Student{})

	fmt.Println(userType.AssignableTo(studentType))  //false
	fmt.Println(studentType.AssignableTo(userType))  //false
	fmt.Println(userType.ConvertibleTo(studentType)) //false
	fmt.Println(studentType.ConvertibleTo(userType)) //false

	userType2 := reflect.TypeOf(User{})
	fmt.Println(userType.AssignableTo(userType2))  //true
	fmt.Println(userType2.ConvertibleTo(userType)) //true
}

func impl() {
	//接口类型获取type的实现方法,nil可以理解为People指针的实例
	peopleType := reflect.TypeOf((*People)(nil)).Elem()
	userType := reflect.TypeOf(User{})
	studentType := reflect.TypeOf(Student{})
	pstudentType := reflect.TypeOf(&Student{})
	fmt.Println(userType.Implements(peopleType))     //false
	fmt.Println(studentType.Implements(peopleType))  //false
	fmt.Println(pstudentType.Implements(peopleType)) //true Student的指针才实现了People的接口
}

五、reflect.Value

a - 空value判断

func is_empty() {
	var i interface{}
	vl := reflect.ValueOf(i)
	fmt.Println(vl)           //<invalid reflect.Value>
	fmt.Println(vl.IsValid()) //false

	var user *User //nil
	vl = reflect.ValueOf(user)
	fmt.Println(vl) //<nil>
	if vl.IsValid() {
		fmt.Println(vl.IsNil()) //true
	}

	var u User
	vl = reflect.ValueOf(u)
	fmt.Println(vl) //{0 false 0}
	if vl.IsValid() {
		fmt.Println(vl.IsZero()) //true
	}

}

b - 获取Value

type User struct {
	age    int64
	Gender bool `json:"sex"`
	uint8
}

func main() {
	iValue := reflect.ValueOf(1)
	sValue := reflect.ValueOf("hello")
	fmt.Println(iValue)                          //1
	fmt.Println(sValue)                          //hello
	fmt.Println(iValue.Kind() == reflect.Int)    //true -> int
	fmt.Println(sValue.Kind() == reflect.String) //true -> string
	// Value转Type
	iType := iValue.Type()
	sType := sValue.Type()
	fmt.Println(iType.Kind() == reflect.Int)    //true -> int
	fmt.Println(sType.Kind() == reflect.String) //true -> string
}

c - 指针Value和非指针Value互相转换

type User struct {
	age    int64
	Gender bool `json:"sex"`
	uint8
}

func main() {
	userPtrValue := reflect.ValueOf(&User{3, true, 6})
	userValue := userPtrValue.Elem()                    //Elem() 指针Value转为非指针Value
	fmt.Println(userValue.Kind(), userPtrValue.Kind())  //struct ptr
	userPtrValue2 := userValue.Addr()                   //Addr() 非指针Value转为指针Value
	fmt.Println(userValue.Kind(), userPtrValue2.Kind()) //struct ptr

}

d - 获取Value对应的原始数据

- 通过Interface()函数把Value转为interface{},再从interface{}强制类型转换,转为原始数据类型
- 在Value上直接调用Int()、String()等
type User struct {
	age    int64
	Gender bool `json:"sex"`
	uint8
}

func main() {
	iValue := reflect.ValueOf(1)
	sValue := reflect.ValueOf("hello")
	fmt.Printf("origin value iValue is %d %d\n", iValue.Interface().(int), iValue.Int())       //origin value iValue is 1 1
	fmt.Printf("origin value sValue is %s %s\n", sValue.Interface().(string), sValue.String()) //origin value sValue is hello hello

	userValue := reflect.ValueOf(User{3, true, 6})
	user := userValue.Interface().(User)
	fmt.Printf("age=%d gender=%t uint=%d\n", user.age, user.Gender, user.uint8) //age=3 gender=true uint=6

	userPtrValue := reflect.ValueOf(&User{2, false, 5})
	user2 := userPtrValue.Interface().(*User)
	fmt.Printf("age=%d gender=%t uint=%d\n", user2.age, user2.Gender, user2.uint8) //age=2 gender=false uint=5

}

e - 通过Value修改原始数据的值

  • 通过反射修改原始数据的值
    • 要想修改原始数据的值,给ValueOf传的必须是指针,而指针Value不能调用Set和FieldByName方法,所以得先通过Elem()转为非指针Value
    • 未导出成员的值不能通过反射进行修改,所以在修改前需要先进行CanSet判断
func main() {
	var i int = 18
	iValue := reflect.ValueOf(&i)
	iValue.Elem().SetInt(28)
	fmt.Println(i) //28

	user := User{10, true, 3}
	userValue := reflect.ValueOf(&user)
	fieldGenderValue := userValue.Elem().FieldByName("Gender")
	fieldGenderValue.SetBool(false)
	fmt.Println(user.Gender) //false

	fieldAgeValue := userValue.Elem().FieldByName("age") //age是未导出的,所以我们需要先使用CanSet判断是否导出再进行设置值
	//fieldAgeValue.SetInt(8)                              //reflect: reflect.Value.SetInt using value obtained using unexported
	if fieldAgeValue.CanSet() {
		fieldAgeValue.SetInt(8)
	} else {
		fmt.Println("age成员未导出,不可以set") //以小写字母开头的成员相当于是私有成员
	}
}

f - 通过Value修改slice

type User struct {
	age    int64
	Gender bool `json:"sex"`
	uint8
}

func main() {
	users := make([]*User, 1, 5) //len=1,cap=5
	users[0] = &User{18, true, 8}
	sliceValue := reflect.ValueOf(&users) //准备通过Value修改users,所以传users的地址
	if sliceValue.Elem().Len() > 0 {      //取得slice的长度
		sliceValue.Elem().Index(0).Elem().FieldByName("Gender").SetBool(false)
		fmt.Printf("1st user Gender change to %t\n", users[0].Gender) //1st user Gender change to false
	}

	//修改slice的len
	sliceValue.Elem().SetLen(2)
	//调用reflect.Value的Set()函数修改其底层指向的原始数据
	sliceValue.Elem().Index(1).Set(reflect.ValueOf(&User{10, false, 3}))
	fmt.Printf("2nd user age %d\n", users[1].age) //2nd user age 10

	//修改slice的cap,新的cap必须位于原始的len到cap之间,即只能把cap改小
	fmt.Printf("slice old cap is %d\n", cap(users)) //slice old cap is 5
	sliceValue.Elem().SetCap(3)
	fmt.Printf("slice new cap is %d\n", cap(users)) //slice new cap is 3
}

g - 通过Value修改map

  • 反射修改map
    • Value.SetMapIndex()函数:往map里添加一个key-value对
    • Value.MapIndex()函数: 根据Key取出对应的map
type User struct {
	age    int64
	Gender bool `json:"sex"`
	uint8
}

func main() {
	u1 := &User{1, true, 2}
	u2 := &User{3, true, 5}
	userMap := make(map[int]*User, 5)
	userMap[0] = u1

	mapValue := reflect.ValueOf(&userMap) //传userMap的地址
	mapValue.Elem().SetMapIndex(reflect.ValueOf(1), reflect.ValueOf(u2))

	for k, user := range userMap {
		fmt.Printf("key = %d, user age = %d\n", k, user.age)
	}

	mapValue.Elem().MapIndex(reflect.ValueOf(0)).Elem().FieldByName("Gender").SetBool(false)
	fmt.Println("u1 Gender = ", u1.Gender) //u1 age =  false
}

六、反射创建对象

  • 通过反射创建struct
type User struct {
	age    int64
	Gender bool `json:"sex"`
	uint8
}

func main() {
	userType := reflect.TypeOf(User{1, false, 2})
	value := reflect.New(userType) //根据reflect.Type创建一个对象,得到该对象的指针,再根据指针提到reflect.Value
	value.Elem().FieldByName("Gender").SetBool(true)

	if userOrign, ok := value.Interface().(*User); ok { //把反射类型转成go原始数据类型Call([]reflect.Value{})
		fmt.Println(userOrign.Gender) //true
	}

}
  • 通过反射创建slice
type User struct {
	age    int64
	Gender bool `json:"sex"`
	uint8
}

func main() {
	sliceType := reflect.TypeOf([]User{})
	sliceValue := reflect.MakeSlice(sliceType, 2, 3)
	sliceValue.Index(0).Set(reflect.ValueOf(User{1, false, 2}))
	sliceValue.Index(1).Set(reflect.ValueOf(User{3, true, 5}))
	users := sliceValue.Interface().([]User)
	fmt.Printf("1st user age %d\n", users[0].age)       //1
	fmt.Printf("2st user Gender %t\n", users[1].Gender) //true

}
  • 通过反射创建map
type User struct {
	Id     int
	age    int64
	Gender bool `json:"sex"`
	Name   string
}

func main() {
	var userMap map[int]*User
	mapType := reflect.TypeOf(userMap)
	// mapValue:=reflect.MakeMap(mapType)
	mapValue := reflect.MakeMapWithSize(mapType, 10)

	user := &User{1, 1, false, "Jack"}
	key := reflect.ValueOf(user.Id)
	mapValue.SetMapIndex(key, reflect.ValueOf(user))                   //SetMapIndex 往map里添加一个key-value对
	mapValue.MapIndex(key).Elem().FieldByName("Name").SetString("Tom") //MapIndex 根据Key取出对应的map
	userMap = mapValue.Interface().(map[int]*User)
	fmt.Printf("user name %s %s\n", userMap[1].Name, user.Name) //user name Tom Tom
}

七、反射调用函数和成员方法

  • 反射调用函数
func Add(a, b int) int {
	return a + b
}

func main() {
	valueFunc := reflect.ValueOf(Add) //函数也是一种数据类型
	typeFunc := reflect.TypeOf(Add)
	argNum := typeFunc.NumIn()            //函数输入参数的个数
	args := make([]reflect.Value, argNum) //准备函数的输入参数
	for i := 0; i < argNum; i++ {
		if typeFunc.In(i).Kind() == reflect.Int {
			args[i] = reflect.ValueOf(3) //给每一个参数都赋3
		}
	}
	sumValue := valueFunc.Call(args) //返回[]reflect.Value,因为go语言的函数返回可能是一个列表
	if typeFunc.Out(0).Kind() == reflect.Int {
		sum := sumValue[0].Interface().(int) //从Value转为原始数据类型
		fmt.Printf("sum=%d\n", sum)          //sum=6
	}

	sumValue = valueFunc.Call([]reflect.Value{reflect.ValueOf(3), reflect.ValueOf(4)})
	if typeFunc.Out(0).Kind() == reflect.Int {
		sum := sumValue[0].Interface().(int) //从Value转为原始数据类型
		fmt.Printf("sum=%d\n", sum)          //sum=7
	}
}
  • 反射调用成员方法
type User struct {
	Id     int
	age    int64
	Gender bool `json:"sex"`
	Name   string
}

func (u *User) GetAge() int64 {
	return u.age
}

func (u User) Think() {
	fmt.Printf("%s is in Think\n", u.Name)
}

func main() {
	user := &User{7, 18, false, "jack"}
	valueUser := reflect.ValueOf(user)               //必须传指针,因为GetAge()在定义的时候它是指针的方法
	bmiMethod := valueUser.MethodByName("GetAge")    //MethodByName()通过Name返回类的成员变量
	resultValue := bmiMethod.Call([]reflect.Value{}) //无参数时传一个空的切片
	result := resultValue[0].Interface().(int64)
	fmt.Printf("GetAge=%d\n", result) //GetAge=18

	//Think()在定义的时候用的不是指针,valueUser可以用指针也可以不用指针
	thinkMethod := valueUser.MethodByName("Think")
	thinkMethod.Call([]reflect.Value{}) //jack is in Think

	valueUser2 := reflect.ValueOf(user)
	thinkMethod = valueUser2.MethodByName("Think")
	thinkMethod.Call([]reflect.Value{}) //jack is in Think
}

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

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

相关文章

分布式算法 - Paxos算法

Paxos算法是Lamport宗师提出的一种基于消息传递的分布式一致性算法&#xff0c;使其获得2013年图灵奖。自Paxos问世以来就持续垄断了分布式一致性算法&#xff0c;Paxos这个名词几乎等同于分布式一致性, 很多分布式一致性算法都由Paxos演变而来。Paxos算法简介Paxos算法是Lampo…

【RabbitMQ笔记05】消息队列RabbitMQ七种模式之Routing路由键模式

这篇文章&#xff0c;主要介绍消息队列RabbitMQ七种模式之Routing路由键模式。 目录 一、消息队列 1.1、Routing模式 1.2、案例代码 &#xff08;1&#xff09;引入依赖 &#xff08;2&#xff09;编写生产者 &#xff08;3&#xff09;编写消费者 一、消息队列 1.1、Ro…

我为什么选择Linux mint 21.1 “Vera“ ? Mint安装优化调教指南(分辨率DPI)

前言&#xff1a;为什么是Mint 笔者算是Linux老用户了&#xff0c;作为一个后端开发&#xff0c;尝试了多种不同发行版。 一开始是Manjaro这种Arch系&#xff0c;但是其对于开发而言实在是太过不稳定&#xff1b;每次滚动更新都要解决很多冲突。不适合当生产力&#xff08;本…

Python实现贝叶斯优化器(Bayes_opt)优化支持向量机分类模型(SVC算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。1.项目背景贝叶斯优化器(BayesianOptimization) 是一种黑盒子优化器&#xff0c;用来寻找最优参数。贝叶斯优化器是基…

动态规划-规划兼职工作

动态规划-规划兼职工作 一、问题描述 你打算利用空闲时间来做兼职工作赚些零花钱。这里有 n 份兼职工作&#xff0c;每份工作预计从 startTime 开始到 endTime 结束&#xff0c;报酬为 profit。给你一份兼职工作表&#xff0c;包含开始时间 startTime&#xff0c;结束时间 en…

Netty入门学习笔记1-定义

1、定义 Netty 是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于快速开发可维护、高性能的网络服务器和客户端。 官网&#xff1a;Netty: Home 2、地位 Netty 在 Java 网络应用框架中的地位就好比&#xff1a;Spring 框架在 JavaEE 开发中的地位 以下的框架都使…

在Kotlin中探索 Activity Results API 极简的解决方案

Activity Results APIActivity Result API提供了用于注册结果、启动结果以及在系统分派结果后对其进行处理的组件。—Google官方文档https://developer.android.google.cn/training/basics/intents/result?hlzh-cn一句话解释&#xff1a;官方Jetpack组件用于代替startActivity…

【Vue学习】Vue高级特性

1. 自定义v-model Vue中的自定义v-model指的是在自定义组件中使用v-model语法糖来实现双向绑定。在Vue中&#xff0c;通过v-model指令可以将表单元素的值与组件实例的数据进行双向绑定。但是对于自定义组件&#xff0c;如果要实现v-model的双向绑定&#xff0c;就需要自定义v-…

Kotlin 高端玩法之DSL

如何在 kotlin 优雅的封装匿名内部类&#xff08;DSL、高阶函数&#xff09;匿名内部类在 Java 中是经常用到的一个特性&#xff0c;例如在 Android 开发中的各种 Listener&#xff0c;使用时也很简单&#xff0c;比如&#xff1a;//lambda button.setOnClickListener(v -> …

每日资源分享(彩虹外链PHP网盘V5.4更新 新增用户系统与分块上传)

demo软件园每日更新资源 1.跟我一起写Python 完整版PDF Python 就为我们提供了非常完善的基础代码库&#xff0c;覆盖了网络、文件、GUI、数据库、文本等大量内容。用 Python 开发&#xff0c;许多功能不必从零编写&#xff0c;直接使用现成的即可。 《跟我一起写 Python》是笔…

C++设计模式(20)——迭代器模式

亦称&#xff1a; Iterator 意图 迭代器模式是一种行为设计模式&#xff0c; 让你能在不暴露集合底层表现形式 &#xff08;列表、 栈和树等&#xff09; 的情况下遍历集合中所有的元素。 问题 集合是编程中最常使用的数据类型之一。 尽管如此&#xff0c; 集合只是一组对…

【数据库】 SQLServer

SQL Server 安装 配置 修改SQL Server默认的数据库文件保存路径_ 认识 master &#xff1a;是SQL Server中最重要的系统数据 库&#xff0c;存储SQL Server中的元数据。 Model&#xff1a;模板数据库&#xff0c;在创建新的数据库时&#xff0c;SQL Server 将会复制此数据…

FreeRTOS的Delay函数

两个Delay函数有两个延时函数vTaskDelay&#xff1a;至少等待指定个数的Tick Interrupt才能变为就绪态xTaskDelayUtil&#xff1a;等待到指定的绝对时刻&#xff0c;才能变为就绪态个人感觉这两个延时函数就是&#xff0c;比如一个我等3个小时&#xff0c;一个是我等到下午3点的…

HTML5 Drag and Drop

这是2个组合事件 dom对象分源对象和目标对象 绑定的事件也是分别区分源对象和目标对象 事件绑定 事件顺序 被拖拽元素&#xff0c;事件触发顺序是 dragstart->drag->dragend&#xff1b; 对于目标元素&#xff0c;事件触发的顺序是 dragenter->dragover->drop/…

Python|每日一练|链表|双指针|数组|递归|图算法|单选记录:删除链表的倒数第 N 个结点|下一个排列|迷宫问题

1、删除链表的倒数第 N 个结点&#xff08;链表&#xff0c;双指针&#xff09; 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 进阶&#xff1a;你能尝试使用一趟扫描实现吗&#xff1f; 示例 1&#xff1a; 输入&#xff1a;head …

ccc-pytorch-感知机算法(3)

文章目录单一输出感知机多输出感知机MLP反向传播单一输出感知机 内容解释&#xff1a; w001w^1_{00}w001​&#xff1a;输入标号1连接标号0&#xff08;第一层&#xff09;x00x_0^0x00​&#xff1a;第0层的标号为0的值O11O_1^1O11​:第一层的标号为0的输出值t&#xff1a;真实…

【Linux】孤儿进程 | 环境变量 | 命令行参数 | 进程优先级

文章目录1. 孤儿进程2. 环境变量1. PATH环境变量证明ls是系统指令修改自己写的可执行程序对应路径2. env——查看系统环境变量3. 获取环境变量envpenvirongetenv 函数获取 (主流)4. 总结3 . 命令行参数理解命令行参数4. 进程优先级优先级与权限的区分为什么会有优先级&#xff…

Android 动态切换应用图标方案

经常听到大家讨论类似的需求&#xff0c;怀疑大厂是不是用了此方案&#xff0c;据我个人了解&#xff0c;多数头部 app 其实都是发版来更新节假日的 icon。当然本方案也是一种可选的方案&#xff0c;以前我也调研过&#xff0c;存在问题和作者所述差不多&#xff0c;此外原文链…

使用Pyparsing为嵌入式开发定义自己的脚本语言

Python在嵌入式开发中也很流行生成实用脚本。Pyparsing还允许你轻松地定义在Python上下文中运行的定制脚本语言。Python实现的系统旨在能够独立执行用户传递的一系列命令。你希望系统以脚本的形式接收命令。用户应该能够定义条件。这种对通信中逻辑元素的最初简单的声音要求&am…

【Hello Linux】初识操作系统

作者&#xff1a;小萌新 专栏&#xff1a;Linux 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;简单介绍下操作系统的概念 操作系统 操作系统是什么&#xff1f; 操作系统是管理软硬件资源的软件 为什么要设计操作系统 为什么要设…