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

C++GO语言微服务项目之 go语言基础语法

目录

01 变量定义

02 自增语法

03 指针

04 go不支持的语法

05 string

06 定长数组-forrange

07 动态数组追加元素

08 切片截取-copy-make介绍

09 map介绍

10 函数

11 内存逃逸

12 import

13 命令行参数-switch

14 标签与continue-goto-break配合使用

15 枚举const-iota

16 结构体基本语法

17 init函数

18 defer-文件读取-匿名函数


01 变量定义

# 二、基础语法

## 1. 变量定义

```go
package main

import "fmt" //goland会帮我们自动导入程序中使用的包

func main() {
    //变量定义: var
    //常量定义: const

    //01-先定义变量,再赋值 var 变量名 数据类型
    var name string
    name = "duke" //Ctrl + Alt +l 可以快速格式化代码

    var age int
    age = 20

    fmt.Println("name:", name)
    fmt.Printf("name is :%s, %d\n", name, age)

    //02 定义时直接赋值
    var gender = "man"
    fmt.Println("gender:", gender)

    //03 定义直接赋值,使用自动推导 (最常用的)
    address := "北京"
    fmt.Println("address:", address)

    //灰色部分表示形参
    test(10, "str")

    //04-平行赋值
    i, j := 10, 20 //同时定义两个变量
    fmt.Println("变换前==》 i:", i, ", j:", j)

    i, j = j, i
    fmt.Println("变换后==》i:", i, ", j:", j)

}

func test(a int, b string) {
    fmt.Println(a)
    fmt.Println(b)
}

```

![1585881281278](assets/1585881281278.png)

02 自增语法

基础数据类型:

```go
int,int8 int16, int32, int64
uint8 ... uint64

float32
float64

true/false
```



## 2. 自增语法

c语言:i++, i--, --i, ++i

go语言:i++, i--, 没有--i,++i, 自增语法必须单独一行

```go
package main

import "fmt"

func main() {
    i := 20
    i++
    //++i //这个也是错的, 语义更加明确
    //fmt.Println("i:", i++)  //这是错误的,不允许和其他代码放在一起,必须单独一行
    fmt.Println("i:", i)

}

```

03 指针

## 3. 指针

```go
package main

import "fmt"

func main() {
    //go语义也有指针
    //结构体成员调用时:   c语言:   ptr->name  go语言:  ptr.name
    //go语言在使用指针时,会使用内部的垃圾回收机制(gc : garbage collector),开发人员不需要手动释放内存
    //c语言不允许返回栈上的指针,go语言可以返回栈上的指针,程序会在编译的时候就确定了变量的分配位置:
    //编译的时候,如果发现有必要的话,就将变量分配到堆上

    name := "lily"
    ptr := &name
    fmt.Println("name:", *ptr)
    fmt.Println("name ptr:", ptr)

    //02-使用new关键字定义
    name2Ptr := new(string)
    *name2Ptr = "Duke"

    fmt.Println("name2:", *name2Ptr)
    fmt.Println("name2 ptr:", name2Ptr)

    //可以返回栈上的指针,编译器在编译程序时,会自动判断这段代码,将city变量分配在堆上
    res := testPtr()
    fmt.Println("res city :", *res, ", address:", res)
    
    //空指针,在c语言: null, c++: nullptr,go: nil

    //if两端不用加()
    //即使有一行代码,也必须使用{}
    if res == nil {
        fmt.Println("res 是空,nil")
    } else {
        fmt.Println("res 是非空")
    }

}

//定义一个函数,返回一个string类型的指针, go语言返回写在参数列表后面
func testPtr() *string {
    city := "深圳"
    ptr := &city
    return ptr
}

04 go不支持的语法

## 4. 不支持的语法汇总

1. 自增--i, ++i不支持
2. 不支持地址加减
3. 不支持三目运算符 ? :
4. 只有false才能代码逻辑假,数字0和nil不能(只有false/true才能表示逻辑真假,数字不能代表逻辑值)

```go
package main

import "fmt"

func main() {
    //if 0 {
    //    fmt.Println("hello")
    //}

    //if nil {
    //    fmt.Println("hello")
    //}

    if true {
        fmt.Println("hello")
    }

    //a, b := 1, 2
    //x := a > b ? 0:-1
}
```



## 5. 字符串string

```go
package main

import "fmt"

func main() {
    //1- 定义
    name := "duke"

    //需要换行,原生输出字符串时,使用反引号``
    usage := `./a.out <option> 
         -h   help 
         -a  xxxx`
    //c语言使用单引号 + \来解决
    fmt.Println("name :", name)
    fmt.Println("usage :", usage)

    //2. 长度,访问
    //C++:   name.length
    //GO: string没有.length方法,可以使用自由函数len()进行处理
    //len: 很常用
    l1 := len(name)
    fmt.Println("l1:", l1)

    //不需要加()
    for i := 0; i < len(name); i++ {
        fmt.Printf("i: %d, v: %c\n", i, name[i])
    }

    //3-拼接
    i, j := "hello", "world"
    fmt.Println("i+j=", i+j)

    //使用const修饰为常量,不能修改
    const address = "beijing" //在编译期就确定了类型,是预处理,所以不需要推导
    const test = 100
    //address = "上海"
    fmt.Println("address:", address)
    
    //可以直接对比字符串,使用ASCII的值进行比较
    if i > j {
        ;
    }
}

```

05 string

## 5. 定长数组

```go
package main

import "fmt"

func main() {

    //1-定义,定义一个具有10个数字的数组
    //c语言定义: int nums[10] ={1,2,3,4}
    //go语言定义:
    //     nums := [10]int{1,2,3,4} (常用方式)
    //  var nums = [10]int{1,2,3,4}
    // var nums [10]int = [10]int{1,2,3,4}

    nums := [10]int{1, 2, 3, 4,0,0,0,0}

    //2-遍历,方式一
    for i := 0; i < len(nums); i++ {
        fmt.Println("i:", i, ", j:", nums[i])
    }

    //方式二: for range   ===> python支持
    //key是数组下标,value是数组的值
    for key, value := range nums {
        //key=0, value=1  => nums[0]
        value += 1
        //value全程只是一个临时变量,不断的被重新赋值,修改它不会修改原始数组
        fmt.Println("key:", key, ", value:", value, "num:", nums[key])
    }

    //在go语言中,如果想忽略一个值,可以使用_
    //如果两个都忽略,那么 就不能使用 := ,而应该直接使用 =
    for _, value := range nums {
        fmt.Println("_忽略key, value:", value)
    }

    //不定长数组定义
    //3-使用make进行创建数组
}
```

06 定长数组-forrange

## 6. 不定长数组(切片、slice)

切片:slice,它的底层也是数组,可以动态改变长度

### - 切片1:

```go
package main

import "fmt"

func main() {
    //切片:slice,它的底层也是数组,可以动态改变长度
    //定义一个切片,包含多个地名
    //names := [10]string{"北京", "上海", "广州", "深圳"}
    names := []string{"北京", "上海", "广州", "深圳"}
    for i, v := range names {
        fmt.Println("i:", i, "v:", v)
    }

    //1.追加数据
    names1 := append(names, "海南")
    fmt.Println("names:", names)
    fmt.Println("names1:", names1)

    fmt.Println("追加元素前,name的长度:", len(names), ",容量:", cap(names))
    names = append(names, "海南")
    //fmt.Println("names追加元素后赋值给自己:", names)
    fmt.Println("追加元素后,name的长度:", len(names), ",容量:", cap(names))

    names = append(names, "西藏")
    fmt.Println("追加元素后,name的长度:", len(names), ",容量:", cap(names))

    //2.对于一个切片,不仅有'长度'的概念len(),还有一个'容量'的概念cap()
    nums := []int{}
    for i := 0; i < 50; i++ {
        nums = append(nums, i)
        fmt.Println("len:", len(nums), ", cap:", cap(nums))
    }
}

```

![1585895660673](assets/1585895660673.png)

小结:

1. 可以使用append进行追加数据
2. len获取长度,cap获取容量
3. 如果容量不足,再次追加数据时,会动态分配2倍空间

### 

07 动态数组追加元素

### - ==切片2:==

```go
package main

import "fmt"

func main() {
    names := [7]string{"北京", "上海", "广州", "深圳", "洛阳", "南京", "秦皇岛"}

    //想基于names创建一个新的数组
    names1 := [3]string{}
    names1[0] = names[0]
    names1[1] = names[1]
    names1[2] = names[2]

    //切片可以基于一个数组,灵活的创建新的数组
    names2 := names[0:3] //左闭右开
    fmt.Println("names2:", names2)

    names2[2] = "Hello"
    fmt.Println("修改names[2]之后, names2:", names2)
    fmt.Println("修改names[2]之后, names:", names)

    //1. 如果从0元素开始截取,那么冒号左边的数字可以省略
    names3 := names[:5]
    fmt.Println("name3:", names3)

    //2. 如果截取到数组最后一个元素,那么冒号右边的数字可以省略
    names4 := names[5:]
    fmt.Println("name4:", names4)

    //3. 如果想从左至右全部使用,那么冒号左右两边的数字都可以省略
    names5 := names[:]
    fmt.Println("name5:", names5)

    //4. 也可以基于一个字符串进行切片截取 : 取字符串的字串 helloworld
    sub1 := "helloworld"[5:7]
    fmt.Println("sub1:", sub1) //'wo'

    //5. 可以在创建空切片的时候,明确指定切片的容量,这样可以提高运行效率
    //创建一个容量是20,当前长度是0的string类型切片
    //make的时候,初始的值都是对应类型的零值 : bool ==> false, 数字==> 0, 字符串 ==> 空
    str2 := make([]string, 10, 20) //第三个参数不是必须的,如果没填写,则默认与长度相同
    fmt.Println("str2:", &str2[0])

    fmt.Println("str2: len:", len(str2), ", cap:", cap(str2))
    str2[0] = "hello"
    str2[1] = "world"

    //6.如果想让切片完全独立于原始数组,可以使用copy()函数来完成
    namesCopy := make([]string, len(names))
    //func copy(dst, src []Type) int
    //names是一个数组,copy函数介收的参数类型是切片,所以需要使用[:]将数组变成切片
    copy(namesCopy, names[:])
    namesCopy[0] = "香港"
    fmt.Println("namesCopy:", namesCopy)
    fmt.Println("naemes本身:", names)

}
```

08 切片截取-copy-make介绍

![1585898372086](assets/1585898372086.png)



## 7.字典(map)

哈希表 , key=>value, 存储的key是经过哈希运算的

```go
package main

import "fmt"

func main() {
    //1. 定义一个字典
    //学生id ==> 学生名字  idNames
    var idNames map[int]string //定义一个map,此时这个map是不能直接赋值的,它是空的

    idNames[0] = "duke"
    idNames[1] = "lily"

    for key, value := range idNames {
        fmt.Println("key:", key, ", value:", value)
    }
}

```



![1585898733163](assets/1585898733163.png)



2. 使用map之前,一定要对map进行分配空间

```go
package main

import "fmt"

func main() {
    //1. 定义一个字典
    //学生id ==> 学生名字  idNames
    var idNames map[int]string //定义一个map,此时这个map是不能直接赋值的,它是空的

    //2. 分配空间,使用make,可以不指定长度,但是建议直接指定长度,性能更好
    idScore := make(map[int]float64)   //这个也是正确的
    idNames = make(map[int]string, 10) //建议使用这种方式

    //3. 定义时直接分配空间
    //idNames1 := make(map[int]string, 10) //这是最常用的方法

    idNames[0] = "duke"
    idNames[1] = "lily"

    //4. 遍历map
    for key, value := range idNames {
        fmt.Println("key:", key, ", value:", value)
    }

    //5. 如何确定一个key是否存在map中
    //在map中不存在访问越界的问题,它认为所有的key都是有效的,所以访问一个不存在的key不会崩溃,返回这个类型的零值
    //零值:  bool=》false, 数字=》0,字符串=》空
    name9 := idNames[9]
    fmt.Println("name9:", name9)               //空
    fmt.Println("idScore[100]:", idScore[100]) //0

    //无法通过获取value来判断一个key是否存在,因此我们需要一个能够校验key是否存在的方式
    value, ok := idNames[1] //如果id=1是存在的,那么value就是key=1对应值,ok返回true, 反之返回零值,false
    if ok {
        fmt.Println("id=1这个key是存在的,value为:", value)
    }

    value, ok = idNames[10]
    if ok {
        fmt.Println("id=10这个key是存在的,value为:", value)
    } else {
        fmt.Println("id=10这个key不存在,value为:", value)
    }

    //6. 删除map中的元素
    //使用自由函数delete来删除指定的key
    fmt.Println("idNames删除前:", idNames)
    delete(idNames, 1)   //"lily"被kill
    delete(idNames, 100) //不会报错
    fmt.Println("idNames删除后:", idNames)

    //并发任务处理的时候,需要对map进行上锁 //TODO
}

```

![1585899844151](assets/1585899844151.png)

09 map介绍

## 8. 函数

```go
package main

import "fmt"

//1.函数返回值在参数列表之后
//2.如果有多个返回值,需要使用圆括号包裹,多个参数之间使用,分割
func test2(a int, b int, c string) (int, string, bool) {
    return a + b, c, true
}

func test3(a, b int, c string) (res int, str string, bl bool) {

    var i, j, k int
    i = 1
    j = 2
    k = 3
    fmt.Println(i, j, k)

    //直接使用返回值的变量名字参与运算
    res = a + b
    str = c
    bl = true

    //当返回值有名字的时候,可以直接简写return
    return

    //return a + b, c, true
}

//如果返回值只有一个参数,并且没有名字,那么不需要加圆括号
func test4() int {
    return 10
}

func main() {
    v1, s1, _ := test2(10, 20, "hello")
    fmt.Println("v1:", v1, ",s1:", s1)

    v3, s3, _ := test3(20, 30, "world")
    fmt.Println("v3:", v3, ", s3:", s3)
}

```

10 函数

内存逃逸:

```go
package main

import "fmt"

func main() {
    p1 := testPtr1()
    fmt.Println("*p1:", *p1)
}

//定义一个函数,返回一个string类型的指针, go语言返回写在参数列表后面
func testPtr1() *string {
    name := "Duke"
    p0 := &name
    fmt.Println("*p0:", *p0)

    city := "深圳"
    ptr := &city
    return ptr
}

```

```go
go build -o test.exe --gcflags "-m -m -l" 11-内存逃逸.go  > 1.txt  2>&1

grep -E "name|city" 1.txt --color
```

![1585902031122](assets/1585902031122.png)



## 9. import

创建目录结构:

![1585903432739](assets/1585903432739.png)



add.go

```go
package add

func add(a, b int) int {
    return a + b
}
```

sub.go

```go
package sub

//在go语言中,同一层级目录,不允许出现多个包名
func Sub(a, b int) int {
    test4() //由于test4与sub.go在同一个包下面,所以可以使用,并且不需要sub.形式
    return a - b
}
```

11 内存逃逸

utils.go

```go
package sub

//package utils //不允许出现多个包名

import "fmt"

func test4() {
    fmt.Println("this is test4() in sub/utils!")
}
```

main.go

```go
package main

import (
    SUB "12-import/sub" //SUB是我们自己重命名的包名
    //"12-import/sub" //sub是文件名,同时也是包名
    . "12-import/sub" //.代表用户在调用这个包里面的函数时,不需要使用包名.的形式,不见一使用的
    "fmt"
)

func main() {
    //res := sub.Sub(20, 10) //包名.函数去调用
    res := SUB.Sub(20, 10) //包名.函数去调用
    fmt.Println("sub.Sub(20,10) =", res)

    res1 := Sub(30, 20)
    fmt.Println("Sub(30, 20) :", res1)

    //这个无法被调用,是因为函数的首写字母是小写的
    //如果一个包里面的函数想对外提供访问权限,那么一定要首写字母大写,
    // 大写字母开头的函数相当于 public,
    // 小写字母开头的函数相当于 private, 只有相同包名的文件才能使用
    //add.add(10,20)
}
```



结果:

![1585903519834](assets/1585903519834.png)

12 import

13 命令行参数-switch

5. 案例:递归遍历指定目录的文件!

```sh
#!/bin/bash

#案例:递归遍历指定目录的文件!
#目录由用户通过命令行传入:

#./recursive.sh ..

recursive()
{
    #接收用户输入的目录
    #currDir="$1"
    local currDir="$1"
    echo "====> 当前目录为:" "$currDir"

    #遍历当前目录
    for i in `ls $currDir`
    do
        #这样才是有效的路径,后续才能正确判断性质
        #item="$currDir+"/"+$i"  <<=== 这是错误的,  /usr/+/+test.txt
        item="$currDir/$i"
        #echo "item: " $item

        #如果i是文件,则打印
        if [ -f "$item" ]; then
            echo "文件找到: $item"
        elif [ -d "$item" ];then
        #如果i是文件夹,则递归遍历
            echo "文件夹找到:" "$item"
            recursive $item
        else
            echo "未知文件:" "$item"
        fi
    done
}

14 标签与continue-goto-break配合使用

#判读输入参数的个数
if [ $# -ne 1 ];then
    echo "Usage: recursive <文件目录>"
    exit
fi

recursive $1
```



## 调试

shell调试参数:

- -n 帮助我们快速检查脚本的语法,而不是逐条执行

  - 脚本如果很大,中间执行过程很长,如果不能实现发现脚本错误,会浪费时间

  - ```sh
     bash -n ./recursive.sh
    ```

  - ![1585713051107](assets/1585713051107.png)



- -x,执行脚本的同时将代码执行过程打印到屏幕,便于追踪

  - bash -x recursive.sh  ==》 作用于整个脚本

  - 可以在代码中,对指定的代码段进行调试  

    - set -x  ==> 启动调试

    - xxxx

    - set +x  ==> 停止调试

      ![1585713439412](assets/1585713439412.png)

- -v,一边执行脚本,一边打印错误输出(很少用)



shift 8  ==> *, 快速定位当前光标所值单词(向下寻找,n)

shift 3 ==> #,  快速定位当前光标所值单词(向上寻找,n)
 

15 枚举const-iota

# 三、正则表达式

1. 以S开头的字符串

   1. ^: 可以限定一个字符开头 

   2. ```sh
      目标:ShelloShello world
      表达式:^Shello
      ```



2. 以数字结尾的字符串

   1. $:可以限定结尾
   2. 表示数字方式:
      1. [0123456789]
      2. [0-9]

   2. ```sh
      目标:helloworld9
      表达式:helloworld[0-9]$
      ```

      

3. 匹配空字符串(没有任何字符)

   1. ^$

4. 字符串只包含三个数字

   1. 三个数字:\[0-9\]\[0-9\]\[0-9\]

5. 字符串只有3到5个字母

   1. 字母表示:
      1. [a-zA-Z], 中间不要加空格
      2. 三个到五个字母:[a-zA-Z]{3,5}
   2. 重复次数{m, n}: 
      1. 匹配前面修饰字符的次数,最少m次,最多n次

6.  匹配不是a-z的任意字符

   1. ^ 在[]内部的时候,表示取反(注意,不是限定开头)
   2. ^[^0-9\] :  以非数字开头的字符
   3. 内反,外头
   4. [^a-z\]    <<<===

7. 字符串有0到1个数字或者字母或者下划线

   1. 表示0-1的方法

      1. {0,1}
      2. ? : 表示0,1个

   2. [a-zA-Z0-9_]?

   3. ```sh
      内容
      hello
      hello1
      hello*
      
      正则:
      hello[a-zA-Z0-9_]?
      
      匹配结果:
      hello
      hello1
      hello
      ```

16 结构体基本语法

2. 字符串有1个或多个空白符号(\t\n\r等)

   1. \s  ==》 代表空格

   2. +:一个或多个

   3. ```h
      内容:hello      world
      
      正则:hello\s+world
      
      结果:hello      world
      ```

3. 字符串有0个或者若干个任意字符(除了\n)

   1.  .: 点,代表任意字符,除了\n

   2. *:星号,重复前一个字符0-n次

   3. 匹配任意字符,任意次数:通常做法,是:   .*   ==> 相当于通配符里面的 *

   4. ```sh
      内容:hello     asdfaasdfasdfadfasdfasdf asdfasdfasdf   world
      正则:hello.*world
      结果:hello     asdfaasdfasdfadfasdfasdf asdfasdfasdf   world
      ```

   5. .{,}  ==> 与 .*效果相同

4. 小结:

   1.  ?    ===> 重复前面一个字符0-1
   2. \+     ===> 重复前面一个字符1-n
   3. \*     ===> 重复前面一个字符0-n
   4. .     ===> 表示任意字符
   5. ^    ===> 限定以某个字符开头
   6. [^a-z] ===> 在方括号内,表示取反(非a-z的任意字符)
   7. $   ===> 限定以某个字符结尾
   8. 数字 ====》 [0123456789]  或[0-9]
   9. 字母 ===> [abcd]  [a-zA-Z]

5. 匹配0或任意多组ABC,比如ABC,ABCABCABC

   1. 使用()进行分组,组成新的匹配单元
   2. (ABC)*

6. 字符串要么是ABC,要么是123

   1. (ABC|123)

   2. ```sh
      内容:
      ABC
      ABCABCABCD 
      123456
      hellowlrd
      
      
      正则:(ABC|123)
      ```

17 init函数

7. 字符串只有一个点号 

   1. ^\\.$

8. 匹配十进制3位整数  :

   1. 0~999 , 5,  10 , 200, 999
   2. 分段匹配:
      1. 一位数:
         1.  [0-9]
      2. 二位数:
         1. [1-9]\[0-9\]
      3. 三位数:
         1. \[1-9\][0-9]{2}
      4. 整合:
         1. ^ ([0-9]|[1-9]\[0-9\]{1,2})$

9. 匹配0-255的整数, ip地址

   1. 分段
      1. 一位:[0-9]
      2. 二位:[1-9]\[0-9\]
      3. 三位:
         - 100- 199
           - 1[0-9]{2}
         - 200-249
           - 2[0-4]\[0-9\]
         - 250-255
           - 25[0-5]
      4. 整合:
         - `^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$`
         - 192.168.1.1

10. 匹配端口号

    1. 0~65536

11. email

    ```sh
    [\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?
    ```

18 defer-文件读取-匿名函数

三种正则表达式:

1. 基础正则:(不使用)  ==》 +?* 都当成普通字符来处理

2. 扩展正则:(我们默认使用这个)==》 +?*  当成特殊字符

3. Perl正则:

   1. +?*是特殊字符

   2. \d ==》 数字 [0-9]

   3. \w ==> 字符[a-zA-Z] 

   4. 用法\d{3}\w    可以匹配:212c

      

# 四、其他命令

## sort(排序)

```sh
-f 忽略字符大小写
-n 按照数值比较
-t 分割字符
-k 指定分割之后比较的字段
-u 只显示一次
-r 反向排序
```

使用:分割之后,截取第三段,以数字的值进行比较,反向打印

```sh
 sort passwd -t: -k3 -n -r
```



## uniq(删除重复)

uniq.txt

```sh
xiaoliu 99 man 25
xiaowen 98 man 24
xiaoliu 99 man 25
```

去重方式,需要重复的两行挨着才能去重,一般和sort配合使用

```sh
cat uniq.txt | sort | uniq
```

![1585728928962](assets/1585728928962.png)



## wc

-l: 统计文件的行数   <==最常用

-c:统计字符

-w:统计单词数量

相关文章:

C++GO语言微服务项目之 go语言基础语法

目录 01 变量定义 02 自增语法 03 指针 04 go不支持的语法 05 string 06 定长数组-forrange 07 动态数组追加元素 08 切片截取-copy-make介绍 09 map介绍 10 函数 11 内存逃逸 12 import 13 命令行参数-switch 14 标签与continue-goto-break配合使用 15 枚举cons…...

DDR在PCB布局布线时的注意事项及设计要点

一、布局注意事项 控制器与DDR颗粒的布局 靠近原则&#xff1a;控制器与DDR颗粒应尽量靠近&#xff0c;缩短时钟&#xff08;CLK&#xff09;、地址/控制线&#xff08;CA&#xff09;、数据线&#xff08;DQ/DQS&#xff09;的走线长度&#xff0c;减少信号延迟差异。 分组隔…...

【每天学习一点点】使用Python的pathlib模块分割文件路径

使用Python的pathlib模块分割文件路径 pathlib模块&#xff08;Python 3.4&#xff09;提供了面向对象的文件系统路径操作方式&#xff0c;比传统的os.path更加直观和易用。以下是使用pathlib分割文件路径的几种方法&#xff1a; 基本路径分割 from pathlib import Path# 创…...

Hydra详细教程:入门、入狱,和使用与注意事项

警告&#xff1a;本文档仅供学习和授权测试目的使用。未经授权对计算机系统进行渗透测试是非法行为。请务必在获得明确许可的情况下使用Hydra&#xff0c;并遵守所有适用的法律法规。滥用此工具可能导致严重的法律后果。 什么是Hydra&#xff1f; Hydra是一款非常流行的开源网…...

【C++游戏引擎开发】第32篇:物理引擎(Bullet)—约束系统

一、约束系统基础理论 1.1 物理约束的本质 1.1.1 约束的数学描述 在刚体动力学中,约束的本质是通过数学方程限制刚体的运动自由度。对于两个刚体A和B的约束关系,可以用以下方程表示: Φ ( q A , q B , t ) = 0...

最新字节跳动运维云原生面经分享

继续分享最新的go面经。 今天分享的是组织内部的朋友在字节的go运维工程师岗位的云原生方向的面经&#xff0c;涉及Prometheus、Kubernetes、CI/CD、网络代理、MySQL主从、Redis哨兵、系统调优及基础命令行工具等知识点&#xff0c;问题我都整理在下面了 面经详解 Prometheus …...

理解 Elasticsearch 的评分机制和 Explain API

作者&#xff1a;来自 Elastic Kofi Bartlett 深入了解 Elasticsearch 的评分机制并探索 Explain API。 想获得 Elastic 认证吗&#xff1f;查看下一期 Elasticsearch Engineer 培训的时间&#xff01; Elasticsearch 拥有大量新功能&#xff0c;帮助你为你的使用场景构建最佳…...

NGINX `ngx_http_charset_module` 字符集声明与编码转换

一、模块定位与功能 ngx_http_charset_module 主要提供两大能力&#xff1a; 响应头声明&#xff1a;在 Content-Type 头部自动添加 ; charsetXXX&#xff0c;告知客户端所用字符集。单向编码转换&#xff1a;在 NGINX 层将一种单字节编码&#xff08;如 koi8-r、windows-125…...

视频编解码学习三之显示器

整理自&#xff1a;显示器_百度百科&#xff0c;触摸屏_百度百科,百度安全验证 分为阴极射线管显示器&#xff08;CRT&#xff09;&#xff0c;等离子显示器PDP&#xff0c;液晶显示器LCD 液晶显示器的组成。一般来说&#xff0c;液晶显示器由以下几个部分组成&#xff1a; […...

Python中的re库详细用法与代码解析

目录 1. 前言 2. 正则表达式的基本概念 2.1 什么是正则表达式&#xff1f; 2.2 常用元字符 3. re库的适应场景 3.1 验证用户输入 3.2 从文本中提取信息 3.3 文本替换与格式化 3.4 分割复杂字符串 3.5 数据清洗与预处理 4. re库的核心功能详解 4.1 re.match()&#…...

K8s网络从0到1

K8s网络从0到1 前言 K8s是一个强大的平台&#xff0c;但它的网络比较复杂&#xff0c;涉及很多概念&#xff0c;例如Pod网络&#xff0c;Service网络&#xff0c;Cluster IPs&#xff0c;NodePort&#xff0c;LoadBalancer和Ingress等等。为了帮助大家理解&#xff0c;模仿TC…...

13.Excel:分列

一 分列的作用 将一个单元格中的内容拆分到两个或多个单元格当中。 二 如何使用 1.常规分列使用 注意&#xff1a;分列功能一次只能拆分一列。 长度一致或者数据间有分隔符。 补充&#xff1a;快速选择一列。 CTRL shift 向下箭头。 补充&#xff1a;中英文逗号不同。 可以先通…...

第十六届蓝桥杯大赛软件赛C/C++大学B组部分题解

第十六届蓝桥杯大赛软件赛C/C大学B组题解 试题A: 移动距离 问题描述 小明初始在二维平面的原点&#xff0c;他想前往坐标(233,666)。在移动过程中&#xff0c;他只能采用以下两种移动方式&#xff0c;并且这两种移动方式可以交替、不限次数地使用&#xff1a; 水平向右移动…...

计算机网络应用层(5)-- P2P文件分发视频流和内容分发网

&#x1f493;个人主页&#xff1a;mooridy &#x1f493;专栏地址&#xff1a;《计算机网络&#xff1a;自顶向下方法》 大纲式阅读笔记_mooridy的博客-CSDN博客 &#x1f493;本博客内容为《计算机网络&#xff1a;自顶向下方法》第二章应用层第五、六节知识梳理 关注我&…...

Gin优雅关闭 graceful-shutdown

文章目录 优雅关闭示例 - Close 方法项目结构使用方法代码如下代码说明如果去掉代码中的数字1&#xff0c;会发生什么 优雅关闭示例项目结构使用方法使用上下文通知不使用上下文通知 代码 notify-without-context-server.go代码说明 代码 notify-with-context-server.go代码说明…...

Android 查看 Logcat (可纯手机方式 无需电脑)

安装 Logcat Reader Github Google Play 如果有电脑 使用其ADB方式可执行如下命令 后续无需安装Termux # 使用 ADB 授予 android.permission.READ_LOGS 权限给 Logcat Reader adb shell "pm grant com.dp.logcatapp android.permission.READ_LOGS && am force-…...

Java 中常见的数据结构及其常用 API

本文总结了 Java 中常见的数据结构及其常用 API&#xff0c;帮助开发者在写算法时能够快速选择合适的数据结构和操作。通过使用合适的 API&#xff0c;可以有效减少计算复杂度&#xff0c;并提高代码的执行效率。 1. 数组 数组是 Java 中最常用的数据结构之一&#xff0c;Jav…...

五子棋html

<!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8" /> <meta name"viewport" content"widthdevice-width, initial-scale1" /> <title>五子棋游戏</title> <style>bo…...

在Laravel 12中实现基于parent_id的树状数组

在Laravel中实现基于parent_id的树状数组&#xff0c;可以通过预加载所有节点并在内存中递归构建树结构来完成。以下是具体步骤和代码示例&#xff1a; 1. 创建模型及数据库迁移 迁移文件&#xff1a; // 创建节点表 Schema::create(nodes, function (Blueprint $table) {$t…...

JavaWeb:后端web基础(TomcatServletHTTP)

一、今日内容 二、Tomcat 介绍与使用 介绍 基本使用 小结 配置 配置 查找进程 三、Servlet 什么是Servlet 快速入门 需求 步骤 1.新建工程-模块&#xff08;Maven&#xff09; 2.修改打包方式-war 3.编写代码 /*** 可以选择继承HttpServlet*/ WebServlet("/hello&q…...

C++负载均衡远程调用学习之负载均衡算法与实现

目录 01 lars 系统架构回顾 02 lars-lbAgentV0.4-route_lb处理report业务流程 03 lars-lbAgentV0.4-负责均衡判断参数配置 04 lars-lbAgentV0.4-负载均衡idle节点的失败率判断 05 lars-lbAgentV0.4-负载均衡overload节点的成功率判断 06 lars-lbAgentV0.4-负载均衡上报提交…...

缓存(1):三级缓存

三级缓存是指什么 我们常说的三级缓存如下&#xff1a; CPU三级缓存Spring三级缓存应用架构&#xff08;JVM、分布式缓存、db&#xff09;三级缓存 CPU 基本概念 CPU 的访问速度每 18 个月就会翻 倍&#xff0c;相当于每年增⻓ 60% 左右&#xff0c;内存的速度当然也会不断…...

Cursor —— AI编辑器 使用详解

Cursor - The AI Code Editor 一、Cursor 是什么&#xff1f; Cursor 是一款优秀的AI代码编辑器&#xff0c;它内置了 Deepseek-R1、GPT-4、Claude等 AI 模型。 简单说&#xff0c;就是&#xff1a;Cursor VS Code 编辑器 AI 大模型 Cursor 功能特性&#xff08;代码补全、…...

Pytorch-CUDA版本环境配置

Pytorch-CUDA版本环境配置 电脑如果是Windows平台下的Nvidia GPU的用户&#xff0c;需配置Pytorch的CUDA版本&#xff0c;分为三步&#xff1a; 1. 安装或更新NVIDA显卡驱动 官方驱动下载地址&#xff1a; https://www.nvidia.cn/Download/index.aspx?langcn 2. 安装CUDA Too…...

一个完整的神经网络训练流程详解(附 PyTorch 示例)

&#x1f9e0; 一个完整的神经网络训练流程详解&#xff08;附 PyTorch 示例&#xff09; &#x1f4cc; 第一部分&#xff1a;神经网络训练流程概览&#xff08;总&#xff09; 在深度学习中&#xff0c;构建和训练一个神经网络模型并不是简单的“输入数据、得到结果”这么简…...

OpenCV 图形API(77)图像与通道拼接函数-----对图像进行几何变换函数remap()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 对图像应用一个通用的几何变换。 函数 remap 使用指定的映射对源图像进行变换&#xff1a; dst ( x , y ) src ( m a p x ( x , y ) , m a p y…...

windows通过wsl安装ubuntu20.04

1 *.bat文件安装hyper-v pushd "%~dp0" dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt for /f %%i in (findstr /i . hyper-v.txt 2^>nul) do dism /online /norestart /add-package:"%SystemRoot%\servicing\Packages\%%i"…...

Spring AI 入门(持续更新)

介绍 Spring AI 是 Spring 项目中一个面向 AI 应用的模块&#xff0c;旨在通过集成开源框架、提供标准化的工具和便捷的开发体验&#xff0c;加速 AI 应用程序的构建和部署。 依赖 <!-- 基于 WebFlux 的响应式 SSE 传输 --> <dependency><groupId>org.spr…...

QUIC协议优化:HTTP_3环境下的超高速异步抓取方案

摘要 随着 QUIC 和 HTTP/3 的普及&#xff0c;基于 UDP 的连接复用与内置加密带来了远超 HTTP/2 的性能提升&#xff0c;可显著降低连接握手与拥塞恢复的开销。本文以爬取知乎热榜数据为目标&#xff0c;提出一种基于 HTTPX aioquic 的异步抓取方案&#xff0c;并结合代理 IP设…...

uni-app实现完成任务解锁拼图功能

界面如下 代码如下 <template><view class"puzzle-container"><view class"puzzle-title">任务进度 {{completedCount}}/{{totalPieces}}</view><view class"puzzle-grid"><viewv-for"(piece, index) in…...