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

【Java转Go】快速上手学习笔记(三)之基础篇二

【Java转Go】快速上手学习笔记(二)之基础篇一

了解了基本语法、基本数据类型这些使用,接下来我们来讲数组、切片、值传递、引用传递、指针类型、函数、map、结构体。

目录

    • 数组和切片
    • 值传递、引用传递
    • 指针类型
    • defer延迟执行
    • 函数
    • map
    • 结构体
      • 匿名结构体(继承)
      • 有名结构体(组合)
    • 方法

数组和切片

数组定义:var 变量名 = [个数]类型{元素}
例如:var arr = [4]int{1, 2, 3, 4}

切片:可以扩容的数组(不指定个数),定义:var 变量名 = []类型{元素}
例如:var arr = []int{1, 2, 3, 4}

/*数组:[个数]类型{元素} arr := [4]int{1, 2, 3, 4}切片:可以扩容的数组 []类型{元素} arr := []int{1, 2, 3, 4}
*/
arr := [4]int{1, 2, 3, 4} // 数组
fmt.Println("数组arr", arr)
slice1 := []int{1, 2, 3, 4} // 切片
fmt.Println("slice1", slice1)

值传递、引用传递

值传递:传递的是原始数据的副本,修改数据(副本)时,并不会对原始数据造成影响

值传递的数据类型:基础类型、array、struct

// updateArr 更改数组里的值
// arr2的值是从arr中复制过来的,这两个数组是两个不同的内存空间,所以修改arr2不会影响arr
func updateArr(arr2 [4]int) {fmt.Println("arr2更改前:", arr2)arr2[0] = 100 // 更改数组里的某个值fmt.Println("arr2更改后:", arr2)
}
// 这里是值传递,将arr传给updateArr函数时,是拷贝操作;也就是说,传过去后在update函数里面就是一个新的数组了,不会影响arr本身
updateArr(arr)
fmt.Println("arr", arr)

引用传递:指向同一个内存空间,所以修改传递的值,也会影响原始数据

引用传递的数据类型:slice、map、channel

// updateSlice 更改切片里的值
func updateSlice(slice2 []int) {fmt.Println("slice2更改前:", slice2)slice2[0] = 100 // 更改切片里的某个值fmt.Println("slice2更改后:", slice2)
}
// slice1传入updateSlice函数中,用slice2接收,这里是引用传递,slice1和slice2指向同一个内存空间。所以当修改slice2时,slice1的值也会改变。
updateSlice(slice1)
fmt.Println("slice1", slice1)

指针类型

我们都知道,当定义一个变量时,会在内存里面开辟一个空间,这个空间有一个地址,这个空间里存放的就是变量的值。

比如:

func main() {var num intfmt.Println("num的地址=", &num) // 这里输出的就是变量num在内存中的地址
}

而指针变量,指向了一个值的内存地址。指针变量也是一个变量,它也可以存值,它存储的值就是另一个变量的地址,而这个指针变量本身也有一个地址。
在这里插入图片描述
基本数据类型在内存的布局:

  • 基本数据类型,变量存的就是值,也叫值类型
  • 获取变量的地址,用&,比如:var num int,获取num的地址用:&num
  • 指针类型,指针变量存的是一个地址,这个地址指向的空间存的才是值,比如:var ptr *int = &num
  • 获取指针类型所指向的值,用:*,比如:var prt *int,使用 *prt 获取ptr指向的值
var i int = 10
fmt.Println("i的地址=", &i) // 0xc00000a0c8
// ptr是一个指针变量,它的类型是 *int,它本身的值是 &i
var ptr *int = &i
fmt.Printf("ptr=%v\n", ptr)     // 这里输出的值是i的地址:0xc00000a0c8
fmt.Printf("ptr的地址=%v\n", &ptr) // 这个指针变量它本身在内存中,也有一个地址:0xc00004a028 
fmt.Printf("ptr指向的值=%v\n", *ptr) // ptr的值是i地址,这个地址所在空间存的值就是i的值:10

defer延迟执行

defer 延迟执行:一个函数或方法的执行被延迟了(放到最后执行)

当有多个defer时,这些defer语句会按照逆序执行(先放进去的后执行)

func f(num int) {fmt.Println(num)
}
// 调用
f(1)
f(2)
defer f(3) // 这里调用f函数时,传了3,这个时候就已经把3传过去了,只是执行的时候放到了最后执行。
f(4)
defer f(5) // 这里比 defer f(3) 先执行
f(6)
defer f(7) // 这里会比 defer f(5)、defer f(3) 先执行
f(8)// 最后打印的结果是:1,2,4,6,8,7,5,3

函数

定义函数用func:func 函数名(参数1,参数2...)(返回值1,返回值2...)

// func 函数名(参数1,参数2...)(返回值1,返回值2...)
// 可以返回多个值(不同类型也可以)
func test1() (int, int, string) {return 100, 200, "hh"
}func test1(a, b int,str1, str2 string) (int, string) {return a + b , str1 + str2
}func main() {num , str := test1(100, 200, "hh", "666")fmt.Println(num , str)
}

写一个递归求和的函数

// 递归求和
func getSum(n int) int {if n > 0 {return getSum(n-1) + n}return 0
}// 调用函数
sum := getSum(5)
fmt.Println(sum)

函数类型:func()本身是一个数据类型 ,它可以作为参数去使用

// 定义一个f1函数
func f1(a, b int) {fmt.Println(a, b)
}// 函数名后面不加括号,函数就是一个类型,加了括号就是函数的调用
// 获取 f1 的类型,输出的结果是 func(int,int)
fmt.Printf("%T\n", f1) // func()、func(int,int)、finc(int,int) int
// 定义函数类型的变量
var f2 func(int, int)
f2 = f1  // 这里f2的内存地址指向的是f1的地址(引用传递)
f3 := f1 // 这里f3的内存地址指向的是f1的地址(引用传递)
fmt.Println(f1) // 输出:0x796120
fmt.Println(f2) // 输出:0x796120
fmt.Println(f3) // 输出:0x796120
// 调用函数
f2(1, 2)
f3(3, 4)

匿名函数:没有名字的函数

// 将一个匿名函数赋值给f4
f4 := func() {fmt.Println("这里是匿名函数f4")
}
f4() // 调用匿名函数
// 匿名函数自己调用自己
func() {fmt.Println("这里是匿名函数f5")
}() //这里后面直接加括号就是调用函数func(a, b int) {fmt.Println("这里是匿名函数f6,a,b=", a, b)
}(50, 100) //这里后面直接加括号就是调用函数// 匿名函数返回值赋值给r
r := func(a, b int) int {fmt.Println("这里是匿名函数f7,a,b=", a, b)return a + b
}(50, 100) //这里后面直接加括号就是调用函数
fmt.Println("r=", r)

回调函数:将函数作为另一个函数的参数

将fun1()函数,作为fun2()函数的参数,则:fun2()函数叫做高阶函数,接收了一个函数作为参数;fun1()函数叫做回调函数,作为另一个函数的参数。

// 高阶函数,可以接收一个函数作为参数(函数本身可以作为参数)
func oper(a, b int, fun func(int, int) int) int {r := fun(a, b)return r
}
func add(a, b int) int {return a + b
}
func sub(a, b int) int {return a - b
}r1 := add(1, 2)
fmt.Println("r1=", r1)r2 := oper(3, 4, add)
fmt.Println("r2=", r2)r3 := oper(8, 4, sub)
fmt.Println("r3=", r3)r4 := oper(3, 4, func(a int, b int) int {if b == 0 {fmt.Println("除数不能为0")return 0}return a / b
})
fmt.Println("r4=", r4)

闭包结构:一个外层函数中,有内层函数,在内层函数中,会操作外层函数的局部变量

  • 并且该外层函数的返回值就是这个内层函数,这个内层函数和外层函数的局部变量,统称为闭包结构
  • 局部变量的生命周期就会发生改变。正常局部变量会随着函数的调用而创建,随着函数的结束而销毁
  • 但是闭包结构中的外层函数的局部变量并不会随着外层函数的结束而销毁,因为内层函数还在继续使用
// 自增
func increment() func() int {i := 0// 定义一个匿名函数,给变量自增并返回fun := func() int { // 内层函数,但是还没有执行// 局部变量声明周期发生了变化i++return i}return fun
}r1 := increment()
fmt.Println(r1)
v1 := r1()
fmt.Println(v1) // 1
v2 := r1()
fmt.Println(v2)   // 2
fmt.Println(r1()) // 3
fmt.Println(r1()) // 4
fmt.Println(r1()) // 5r2 := increment()
v3 := r2()
fmt.Println(v3)   // 1
fmt.Println(r1()) // 6 这里r1里面的局部变量并没有被销毁,所以继续自增
fmt.Println(r2()) // 2

map

map定义:可以使用内建函数 make 或使用 map 关键字来定义 Map

  • make定义:
    • myMap := make(map[键类型]值类型, 初始容量) // 创建一个空的 Map

    • myMap := make(map[string]int)、m := make(map[string]int, 10) // 创建一个初始容量为 10 的 Map

    • 当map中的键值对数量超过了初始容量时,map会自动扩容;如果不指定初始容量,Go会根据实际情况选择一个合适的值。

  • map定义:myMap := map[键类型]值类型{} // 使用字面量创建 map
package mainimport "fmt"func main() {mapUse()
}// map用例
func mapUse() {/*map定义:可以使用内建函数 make 或使用 map 关键字来定义 Mapmake定义:myMap := make(map[键类型]值类型, 初始容量) // 创建一个空的 MapmyMap := make(map[string]int)、m := make(map[string]int, 10) // 创建一个初始容量为 10 的 Map当map中的键值对数量超过了初始容量时,map会自动扩容;如果不指定初始容量,Go会根据实际情况选择一个合适的值。map定义:myMap := map[键类型]值类型{} // 使用字面量创建 map*/// 创建一个空的 Map//m := make(map[string]int)// 创建一个初始容量为 10 的 Map//m := make(map[string]int, 10)// 使用字面量创建 Mapm := map[string]int{"apple":  1,"banana": 2,"orange": 3,}// 获取键值对v1 := m["apple"]//v2, isKey := m["apple"] // 如果键存在,isKey 的值为 truev2, isKey := m["pear"] // 如果键不存在,isKey 的值为 false,v2 的值为该类型的零值fmt.Println(v1)fmt.Println(v2, isKey)// 修改元素m["apple"] = 5// 获取 Map 的长度mlen := len(m)fmt.Println("m的长度=", mlen)// 遍历 Mapfor k, v := range m {fmt.Printf("key=%s, value=%d\n", k, v)}// 删除元素delete(m, "banana")mlen = len(m)fmt.Println("删除banana后,m的长度=", mlen)// 定义一个mapvar siteMap map[string]stringsiteMap = make(map[string]string)// map中插入 key - value 对siteMap["xunyu"] = "迅羽"siteMap["baiye"] = "白夜"siteMap["chiling"] = "炽翎"siteMap["yunmo"] = "云墨"siteMap["yuelun"] = "月轮"// 遍历key,通过key拿到valuefor site := range siteMap {fmt.Println(site, "的名字是", siteMap[site])}//查看元素在集合中是否存在name, ok := siteMap["fuhua"] // 如果确定是真实的,则存在,否则不存在fmt.Println(name, ok)if ok {fmt.Println("fuhua 的 名字是", name)} else {fmt.Println("fuhua 的名字不存在")}
}

结构体

结构体其实就相当于Java中的实体对象。

定义 struct 结构体:结构体定义需要使用 type 和 struct 语句。

  • struct 语句定义一个新的数据类型,结构体中有一个或多个成员(属性)。
  • type 语句设定了结构体的名称。
  • 格式如下:type 结构体名称 struct {
        属性1 类型
        属性2 类型
        属性3 类型
        …
    }
  • 一旦定义了结构体类型,它就能用于变量的声明,语法如下:
    • 1、结构体实例化变量 := 结构体名称 {value1, value2…valuen}
    • 2、结构体实例化变量 := 结构体名称 { key1: value1, key2: value2…, keyn: valuen}

还有一点要注意,还有一点要注意,定义的结构体如果只在当前包内使用,那么结构体名称和属性名大小写无所谓。如果要在其他包使用,则结构体名、属性名的首字母必须要大写。。这个就类似于Java的public和private,首字母大写是public,首字母小写是private。

// 定义一个结构体:用户信息
type SysUser struct {userName string // 用户账号realName string // 真是姓名password string // 用户密码phone    string // 手机号码address  string // 用户地址state    int    // 状态(0 正常 1 禁用)
}// 补充:结构体标签
type Article struct {Title     string `json:"title"` // 这样写结构体进行json转换的时候,Title就会自动变为titleDesc      string `json:"desc"`Content   string `json:"content"`Username  string `json:"-"` // - 也不参与序列化LookCount int    `json:"look_count"`Free      bool   `json:"free"`password  string // 小写字母开头的不会参与序列化
}// 结构体使用(结构体其实就相当于Java的实体对象)
func structUse() {// 创建一个新的结构体(实例化结构体),这种方式实例化,就需要将全部属性都赋值,并且一一对应// 类似于Java的有参构造函数(只不过Java的有参构造可以选哪几个属性传参,而这个需要全部属性都赋值传过去)fmt.Println(SysUser{"fuhua", "符华", "fuhua123", "13245778412", "广东省惠州市", 0})// 也可以使用 key => value 格式,通过key进行赋值,这种方式就不用说全部的属性都赋值了,而是可以自己选哪些属性进行赋值,忽略的字段为 0 或 空fmt.Println(SysUser{userName: "baiye", realName: "白夜", password: "baiye123", phone: "15125552365"})// 声明SysUser变量var user1 SysUservar user2 SysUser// 如果要访问结构体属性,直接 结构体变量名.属性 或者 指针变量.属性 就行// 给user1对象属性赋值user1.userName = "yunmo"user1.realName = "云墨"user1.password = "yunmo123"user1.phone = "15422667878"user1.address = "广东省惠州市"user1.state = 0// 给user2对象属性赋值user2.userName = "yuelun"user2.realName = "月轮"user2.password = "yuelun123"user2.state = 0fmt.Println("用户 1 的信息 : ", user1)printUser(user2) // 结构体作为函数的参数,值传递// 结构体指针,和普通的指针是一样的,声明:var 指针变量名称 *结构体 = &结构体变量//var userPoint *SysUser // 这个指针是SysUser类型的//userPoint = &user1 // user1是SysUser的一个实例化对象,&user1就是把这个结构体的内存地址赋值给了userPointvar userPoint *SysUser = &user1// 使用这个指针的时候,通过 *指针变量名称 就可以把指针存的user1的地址对应的值给取出来了。fmt.Println("使用结构体指针,打印用户1", *userPoint) // *userPoint 的效果和直接用 user1 打印的效果一样// 使用结构体指针访问结构体成员,使用 "." 操作符fmt.Println("使用结构体指针,访问用户1 userName : ", userPoint.userName) // 这个效果相当于 user1.userNameprintUserPoint(&user2) // 结构体指针作为函数的参数,引用传递fmt.Println("结构体指针用户信息更改后")fmt.Printf("结构体指针用户 userName : %s\n", user2.userName) // 这里 userName 的值由 yuelun 变成了 xunyufmt.Printf("结构体指针用户 realName : %s\n", user2.realName) // 这里 userName 的值由 月轮 变成了 迅羽fmt.Printf("结构体指针用户 password : %s\n", user2.password)fmt.Printf("结构体指针用户 state : %d\n", user2.state)
}// 结构体作为函数的参数:值传递
func printUser(user SysUser) {fmt.Printf("用户 userName : %s\n", user.userName)fmt.Printf("用户 realName : %s\n", user.realName)fmt.Printf("用户 password : %s\n", user.password)fmt.Printf("用户 state : %d\n", user.state)
}// 结构体指针作为函数的参数:引用传递
func printUserPoint(user *SysUser) {fmt.Println("结构体指针用户信息更改前")fmt.Printf("结构体指针用户 userName : %s\n", user.userName)fmt.Printf("结构体指针用户 realName : %s\n", user.realName)fmt.Printf("结构体指针用户 password : %s\n", user.password)fmt.Printf("结构体指针用户 state : %d\n", user.state)user.userName = "xunyu"user.realName = "迅羽"
}

匿名结构体(继承)

Go里面也有继承,在某个结构体A里面,嵌套了一个匿名结构体B,那么就A就继承了B的所有属性和方法(注意如果A、B在不同包,那么A的属性、方法首字母必须大写,B才能访问)。

语法:

type goods struct {name string,price fload64
}
type book struct{goods, // 这里就是匿名结构体goods,这样book就继承了goods的属性和方法writer string
}

当结构体和匿名结构体有相同的属性或方法时,编译器采用就近原则,如果想访问匿名结构体的属性和方法,可以通过匿名结构体名来进行区分


当结构体里面有多个匿名结构体(多重继承),并且这多个匿名结构体里有同名的属性或方法,则访问这些属性和方法时,必须要指定匿名结构体,否则编译报错

type 商品 struct {name  stringprice float64
}func (a *商品) show() {fmt.Println("商品 name=", a.name)
}type 家电 struct {name  stringbrand string
}func (a *家电) show() {fmt.Println("家电 name=", a.name)
}type 电脑 struct {name string // 和匿名结构体的name属性相同商品          // 这里就是匿名结构体商品(嵌套了 商品 结构体,但是没有指定名字),这样 电脑 就继承了 商品 的属性和方法家电          // 这里就是匿名结构体商品(嵌套了 家电 结构体,但是没有指定名字),这样 电脑 就继承了 家电 的属性和方法
}type 打印机 struct {*商品 // 这里就是匿名结构体商品(嵌套了 商品 结构体,但是没有指定名字),这样 打印机 就继承了 商品 的属性和方法*家电 // 这里就是匿名结构体商品(嵌套了 家电 结构体,但是没有指定名字),这样 打印机 就继承了 家电 的属性和方法
}func main() {// 匿名结构体//var a 电脑//a.name = "联想Y9000" // 电脑 的name属性和匿名结构体属性同名了,采用就近原则,这里访问的是电脑的name属性,而不是商品或家电的name属性//a.price = 7000.0   // 这个是 商品 的属性,然后没有和其他结构体重名,所以可以直接调用//a.brand = "联想"     // 这个是 家电 的属性,然后没有和其他结构体重名,所以可以直接调用//a.商品.name = "电脑"   // 如果要访问匿名结构体的属性,可以通过匿名结构体去访问//a.家电.name = "联想"   // 如果要访问匿名结构体的属性,可以通过匿名结构体去访问a.show() // 因为匿名结构体 商品、家电 都有show方法,并且 电脑 自己本身没有同名方法,所以调用show时,必须要指定是哪个匿名结构体的show方法,否则报错:引用不明确//a.商品.show() // 必须指定匿名结构体//a.家电.show() // 必须指定匿名结构体//a := 电脑{"联想Y9000", 商品{"电脑", 7000.0}, 家电{"联想", "联想"}}//a := 电脑{"联想Y9000", 商品{name: "电脑", price: 7000.0}, 家电{name: "联想", brand: "联想"}}//a.商品.show() // 必须指定匿名结构体//a.家电.show() // 必须指定匿名结构体a := 打印机{&商品{name: "打印机", price: 3000.0}, &家电{name: "打印机", brand: "惠普"}}fmt.Println(a) // 这里打印的是商品、家电的地址//fmt.Println(a.商品, a.家电)fmt.Println(*a.商品, *a.家电)
}

有名结构体(组合)

有名结构体,又叫 组合

结构体嵌套了一个有名结构体,这种模式叫组合,如果是组合关系,那么在访问组合的结构体的方法或属性时,必须带上结构体的名字。

也就是说:在结构体A中,嵌套了一个结构体B,并且给B命名为b,那么就b相当于是一个B类型的变量。A同样可以访问B的所有属性和方法,只不过给B命名之后,要调用B里面的属性或方法,必须要结构体的名字。

type 书籍 struct {g 商品 // 这里给嵌套的结构体命名了,那么 书籍 和 商品 就是组合关系
}func main() {// 有名结构体var b 书籍b.g.name = "《Go从入门到入土》" // 访问有名结构体里面的属性,必须要带上有名结构体名称b.g.show()
}

方法

方法和函数是不一样。方法是作用于指定的数据类型上的,也就是说和指定的数据类型绑定。自定义的类型(用type声明)都可以有方法,不只是结构体。

方法定义:func (变量名 数据类型) 方法名(参数 参数类型) 返回类型 {}

方法比函数多了 要绑定的数据类型。

比如:user结构体,它有一个方法,那这个方法就是和user绑定的,在 func (变量名 数据类型) 这里 数据类型 就是user类型

调用函数直接用 函数名() 即可,但是方法需要用变量.出来调用,比如一个结构体的方法,需要用 结构体变量.方法() 调用。


  • 函数:如果参数是值类型,则调用的时候只能是值类型,不能传引用类型,反之亦然。

  • 方法:

    • 如果参数是值类型,调用的时候可以是引用类型也可以是值类型,反之亦然。
    • 但是本质上是值类型还是引用类型,需要看方法的参数是用的是值类型还是引用类型。
    • 例如:func (u *user) SetAge(age int) {}
      • SetAge()方法,参数是 u *user,因为用的是指针,所以是引用类型;
      • 那么调用这个方法的时候,无论是用 u.SetAge()(这种调用方式其实是等价于 (&u).SetAge() 的) 还是 &u.SetAge(),其实都是引用传递。
      • 如果把 u *user 改成 u user,那么这里就是值类型,调用时,无论是用 u.SetAge() 还是 &u.SetAge(),都是值传递。

这里不知道大家能不能明白,我看视频的时候是看懂了,但是用文字总结出来的时候,总感觉说不清楚🤣

大家直接看下案例吧

person.go 这个文件在model包下

// 定义一个person结构体
type person struct {Name      string  // 姓名 首字母大写其他包可以访问accountNo string  // 账号(长度在6-10位之间) 首字母小写其他包无法访问pwd       string  // 密码(长度8-20)age       int     // 年龄(0-150)balance   float64 // 余额(大于0)
}// 写一个工厂模式函数,相当于构造函数(返回指针类型)
func NewPerson(name string) *person {return &person{Name: name}
}// 为了在其他包访问 accountNo、pwd、age、balance,我们编写一对setter、getter方法
// 这里 (p *person) 绑定的是person的指针类型,那么调用这个方法的时候,无论是用 p.SetAccountNo() 还是 &p.SetAccountNo(),其实都是引用传递
func (p *person) SetAccountNo(accountNo string) {// 账号长度在6-10之间,允许字母、数字、下划线,以字母开头rex := "^[a-zA-Z][a-zA-Z0-9_]{6,10}$"b, _ := regexp.MatchString(rex, accountNo)if !b {fmt.Println("账号格式错误,账号长度在6-10之间,允许字母、数字、下划线,以字母开头")}p.accountNo = accountNo
}
// (p person) 这里就是值传递了,那么调用这个方法的时候,无论是用 p.SetAccountNo() 还是 &p.SetAccountNo(),都是值传递
// func (p person) SetAccountNo(accountNo string) {}func (p *person) GetAccountNo() string {return p.accountNo
}func (p *person) SetPwd(pwd string) {// 密码长度在8-20之间,必须包含数字、大小写字母、特殊字符串rex := "^[a-zA-Z][a-zA-Z0-9_]{8,20}$"b, _ := regexp.MatchString(rex, pwd)if !b {fmt.Println("密码格式错误,密码长度在8-20之间,允许字母、数字、下划线,以字母开头")}p.pwd = pwd
}
func (p *person) GetPwd() string {return p.pwd
}

main.go 这个文件在main包下

import ("fmt""go-demo1/model" // 这里引入model包(go-demo1是项目名)
)func main() {// NewPerson返回的是指针类型p := model.NewPerson("符华") // model包,点出这个包里面的NewPerson函数p.SetAccountNo("fu_hua01")p.SetPwd("fuhua_001")p.SetAge(20)p.SetBalance(100000)
}

相关文章:

【Java转Go】快速上手学习笔记(三)之基础篇二

【Java转Go】快速上手学习笔记(二)之基础篇一 了解了基本语法、基本数据类型这些使用,接下来我们来讲数组、切片、值传递、引用传递、指针类型、函数、map、结构体。 目录 数组和切片值传递、引用传递指针类型defer延迟执行函数map结构体匿名…...

【vue 引入pinia与pinia的详细使用】

vue引入pinia与使用 安装引入使用定义 store在组件中使用 store在插件中使用 store配置 store 总结 Pinia 是一个用于 Vue 3 的状态管理库,其设计目标是提供一个简单、一致的 API 和强类型支持。下面介绍如何引入 Pinia 并使用它。 安装 npm install pinia引入 在…...

USACO18DEC Fine Dining G

P5122 [USACO18DEC] Fine Dining G 题目大意 有一个由 n n n个点 m m m条边构成的无向连通图,这 n n n个点的编号为 1 1 1到 n n n。前 n − 1 n-1 n−1个点上都有一头奶牛,这些奶牛都要前往 n n n号点。第 i i i条边连接 a i a_i ai​和 b i b_i bi​…...

fckeditor编辑器的两种使用方法

需要的资源包我放我资源里了&#xff0c;不要积分 https://download.csdn.net/download/wybshyy/88245895 首先把FredCK.FCKeditorV2.dll添加到引用 具体方法如下&#xff0c;一个是客户端版本&#xff0c;一个是服务器端版本 客户端版本&#xff1a; <% Page Language…...

数据结构,查找算法(二分,分块,哈希)

一、查找算法 1、二分查找:(前提条件: 必须有序的序列) #include <stdio.h> //二分查找 value代表的是被查找的值 int findByHalf(int *p, int n, int value) {int low = 0;//low低int high = n-1;//high高int middle;//用来保存中间位置的下标while(low <= high…...

C++(Qt)软件调试---gdb调试入门用法(12)

gdb调试—入门用法&#xff08;1&#xff09; 文章目录 gdb调试---入门用法&#xff08;1&#xff09;1、前言1.1 什么是GDB1.2 为什么要学习GDB1.3 主要内容1.4 GDB资料 2、C/C开发调试环境准备3、gdb启动调试1.1 启动调试并传入参数1.2 附加到进程1.3 过程执行1.4 退出调试 4…...

shell和Python 两种方法分别画 iostat的监控图

在服务器存储的测试中,经常需要看performance的性能曲线&#xff0c;这样最能直接观察HDD或者SSD的性能曲线。 如下这是一个针对HDD跑Fio读写的iostat监控log,下面介绍一下分别用shell 和Python3 写画iostat图的方法 1 shell脚本 环境:linux OS gnuplot工具 第一步 :解析iosta…...

设计模式(9)建造者模式

一、 1、概念&#xff1a;将一个复杂对象的构造与它的表示分离&#xff0c;使得同样的构造过程可以创建不同的表示。建造者模式主要用于创建一些复杂的对象&#xff0c;这些对象内部构建间的顺序通常是稳定的&#xff0c;但对象内部的构建通常面临着复杂的变化&#xff1b;建造…...

PHP 创业感悟交流平台系统mysql数据库web结构apache计算机软件工程网页wamp

一、源码特点 PHP 创业感悟交流平台系统&#xff08;含论坛&#xff09;是一套完善的web设计系统&#xff0c;对理解php编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 源码下载&#xff1a; https://download.csdn.…...

工作流程引擎之flowable(集成springboot)

0、背景 现状&#xff1a;公司各部门业务系统有各自的工作流引擎&#xff0c;也有cross function的业务在不同系统或OA系统流转&#xff0c;没有统一的去规划布局统一的BPM解决方案&#xff0c;近期由于一个项目引发朝着整合统一的BPM方案&#xff0c;特了解一下市面上比较主流…...

leetcode54. 螺旋矩阵(java)

螺旋矩阵 题目描述解题 收缩法 上期经典算法 题目描述 难度 - 中等 原题链接 - leecode 54 螺旋矩阵 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7…...

go gorm 查询

定义model package mysqltestimport ("errors""fmt""gorm.io/gorm" )type Product struct {gorm.ModelID uint gorm:"primarykey"Name string gorm:"column:name"Price float64 gorm:"column:price_value&quo…...

Flutter GetXController 动态Tabbar 报错问题

场景&#xff1a; 1.Tabbar的内容是接口获取的 2. TabController? tabController;&#xff1b; 在onInit 方法中初始化tabbarController tabController TabController(initialIndex: 0, length: titleDataList.length, vsync: this); 这时候会报一个错误 Controllers l…...

Redis(缓存预热,缓存雪崩,缓存击穿,缓存穿透)

目录 一、缓存预热 二、缓存雪崩 三、缓存击穿 四、缓存穿透 一、缓存预热 开过车的都知道&#xff0c;冬天的时候启动我们的小汽车之后不要直接驾驶&#xff0c;先让车子发动机预热一段时间再启动。缓存预热是一样的道理。 缓存预热就是系统启动前&#xff0c;提前将相关的…...

UE4/5Niagara粒子特效学习(使用UE5.1,适合新手)

目录 创建空模板 创建粒子 粒子的基础属性 粒子的生命周期 颜色 大小设置 生成的位置 Skeletal Mesh Location的效果&#xff1a; Shape Location 添加速度 添加Noise力场 在生成中添加&#xff1a; 效果&#xff1a; ​编辑 在更新中添加&#xff1a; 效果&…...

from moduleA import * 语句 和import moduleA 的区别

from moduleA import * 语句和import moduleA 的区别是&#xff1a; from moduleA import * 语句会将moduleA模块中的所有内容&#xff08;函数、变量、类等&#xff09;直接导入到当前模块的命名空间中&#xff0c;这样就可以直接使用它们&#xff0c;而不需要加上模块名的限…...

【leetcode 力扣刷题】交换链表中的节点

24. 两两交换链表中的节点 24. 两两交换链表中的节点两两节点分组&#xff0c;反转两个节点连接递归求解 24. 两两交换链表中的节点 题目链接&#xff1a;24. 两两交换链表中的节点 题目内容&#xff1a; 题目中强调不能修改节点内部值&#xff0c;是因为如果不加这个限制的话…...

学会Mybatis框架:让你的代码更具灵活性、可维护性、安全性和高效性【二.动态SQL】

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Mybatis的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.Mybatis动态SQL如何应用 1.需求 2.…...

Oracle 中 ROWNUM 使用问题记录

ROWNUM 使用问题记录(2023-08-17) Oracle 版本&#xff1a; 19.0.0.0.0 Enterprise现象&#xff1a;今天在项目遇到一个问题&#xff0c;测试人员反馈前一天能看到的数据今天看不到了 用表格举例&#xff0c;这是前一天看到的数据&#xff0c;有9、7、1 这几个数量信息 日期…...

MySQL数据库:内置函数

日期函数 规定&#xff1a;日期&#xff1a;年月日 时间&#xff1a;时分秒 函数名称作用描述current_date()当前日期current_time()当前时间current_timestamp()当前时间戳date(datetime)返回datetime参数的日期部分date_add(date,interval d_value_type)在date中添加…...

【C++杂货铺】探索string的底层实现

文章目录 一、成员变量二、成员函数2.1 默认构造函数2.2 拷贝构造函数2.3 operator2.4 c_str()2.5 size()2.6 operator[ ]2.7 iterator2.8 reserve2.9 resize2.10 push_back2.11 append2.12 operator2.13 insert2.14 erase2.15 find2.16 substr2.17 operator<<2.18 opera…...

c++ day1

定义一个命名空间Myspace&#xff0c;包含以下函数&#xff1a;将一个字符串中的所有单词进行反转&#xff0c;并输出反转后的结果。例如&#xff0c;输入字符串为"Hello World"&#xff0c;输出结果为"olleH dlroW"&#xff0c;并在主函数内测试该函数。 …...

变动的Python爬虫实现

在电商时代&#xff0c;了解商品价格的变动对于购物者和卖家来说都非常重要。本文将分享一种基于Python的实时监控电商平台商品价格变动的爬虫实现方法。通过本文的解决方案和代码示例&#xff0c;您将能够轻松监控商品价格&#xff0c;并及时做出决策。 一、了解需求和目标 在…...

mybatis-plus--配置-(sql)日志输出-自动填充-分页-多数据源-逻辑删除

写在前面&#xff1a; 本文主要介绍mybatis-plus的配置&#xff0c;以后在有的时候在补充。欢迎交流。 文章目录 日志输出自动填充分页全局字段配置多数据源 日志输出 调试的时候需要看执行的sql&#xff0c;这时候就很需要日志来记录查看了。 mybatis-plus的日志配置在yml…...

数据API服务管理功能:解放数据潜力,提升业务效率

数据API服务的重要性 在数字化时代&#xff0c;数据被认为是企业的重要资产。数据API服务的管理功能能够有效帮助企业实现数据的整合和利用。通过合理的数据API服务管理&#xff0c;企业可以更好地解放数据潜力&#xff0c;提升业务效率。 ​ 解放数据潜力 数据API服务管理功…...

云南森林火灾vr消防模拟安全演练系统训练消防员火灾和事故的适应和应对能力

据统计,每一场破坏性地震发生后,会引发次生的灾害,而火灾是其中之一。导致火灾的原因,推测是地震时使供电线路短路,引燃易燃物,火灾就随即发生。所以,在日常生活中,定期的消防演练还是非常必要的, VR消防&#xff0c;是VR公司深圳华锐视点利用VR虚拟现实技术&#xff0c;将VR和…...

(6)(6.2) 任务命令

文章目录 前言 6.2.1 概述 6.2.2 导航命令 6.2.3 条件命令 6.2.4 DO命令 前言 本文介绍了 Copter、Plane 和 Rover 切换到自动模式时支持的任务指令。 &#xff01;Warning 这是一项正在进行中的工作&#xff0c;尚未经过全面审核。有关 Copter 的更佳列表&#xff0c;请…...

【consul】

consul 一、什么是服务注册与发现1.11.2 二、 什么是consul2.1定义2.2特性2.2.1服务注册与发现&#xff1a;2.2.2健康检查&#xff1a;2.2.3Key/Value存储&#xff1a; 三、consul部署-datacenter &#xff1a;指定数据中心名称&#xff0c;默认是dc1。consul &#xff1a;指定…...

Electron环境搭建

Electron是一个优秀的开源框架&#xff0c;用于构建跨平台的桌面应用程序。它基于Chromium和Node.js&#xff0c;使得开发者可以使用Web技术&#xff08;HTML、CSS和JavaScript&#xff09;来构建可在Windows、macOS和Linux等多个操作系统上运行的应用程序。本文将介绍如何搭建…...

MinIO线上扩容实战

硬件投入肯定是随着业务的增长而增长&#xff0c;这就要求中间件平台必须提供水平伸缩机制&#xff0c;MinIO对象存储服务也不例外&#xff0c;本文就详细介绍MinIO的扩容。 Minio支持通过增加新的Server Pool来扩容老的集群。每个Server Pool都是一个相对独立的故障域&#x…...

aspcms网站地图/百度知道问答首页

骁龙780G&#xff1a;搭载全新的5nm制作工艺&#xff0c;为用户提供很好的手机旗舰功耗管理 我用的手机就是活动时8折抢购的 点击开抢http://shouji.adiannao.cn/7 骁龙778G&#xff1a;搭载6nm制作工艺&#xff0c;这是目前性价比很好的芯片制作工艺 骁龙780G&#xff1a;在芯…...

中堂仿做网站/平面设计培训

1、加载父类&#xff0c;加载父类的静态属性和静态代码块 2、加载子类&#xff0c;加载子类的静态属性和静态代码块 3、初始化父类中的非静态属性并赋初值&#xff0c;执行父类非静态代码块&#xff0c;执行父类构造。 4、初始化子类中的非静态属性并赋初值&#xff0c;执行代码…...

网站建设 软件开发/百度推广服务费一年多少钱

下面的操作都是在linux下进行的&#xff0c;我用的Ubuntu。切换到su超级用户。 1.下载源码&#xff0c;有各种方法&#xff1a; ①你如果能访问谷歌的话&#xff0c;直接用git下载。 ②不能访问谷歌&#xff0c;那就搜索下载源码压缩包&#xff08;搜不到的可以联系我&#…...

学校网站建设的安全策略/天津seo选天津旗舰科技a

其实&#xff0c;两者之间是没有多大差别的&#xff0c;只是为了提高查找效率而区分的。当你包含一个头文件时&#xff0c;编译时&#xff0c;需要找到那个头文件&#xff0c;使用<>这种方式&#xff0c;编译器查找的时候&#xff0c;会在编译器的安装目录的标准库中开始…...

网站备案繁琐工作/搜索引擎网页

MySQL Cluster 是一种技术&#xff0c;该技术允许在无共享的系统中部署“内存中”数据库的 Cluster 。通过无共享体系结构&#xff0c;系统能够使用廉价的硬件&#xff0c;而且对软硬件无特殊要求。此外&#xff0c;由于每个组件有自己的内存和磁盘&#xff0c;不存在单点故障。…...

潍坊 网站建设/各大引擎搜索入口

上半年流畅度的新机排名&#xff0c;哇&#xff01;第一名居然是这款2019-05-11 22:26:4510点赞6收藏29评论要了解更多流行资讯、玩机技巧、数码体验、科普深扒&#xff0c;点击右上角关注我-----------2019年到现在已经过半了&#xff0c;各大手机厂商的新机发布热潮也慢慢降了…...