GO语言开篇-Go语言急速入门(基础知识点)| 青训营笔记

news2024/11/28 18:58:53

文章目录

  • 一.GO语言应用场景
    • 1.1 前言
    • 1.2 什么是GO语言
    • 1.3 仅仅10行完成高并发的服务器
  • 二.入门
    • 2.1 基础语法-HelloWorld
    • 2.2 基础语法-变量类型
      • 2.2.1 变量
      • 2.2.2 if else
      • 2.2.3 循环
      • 2.2.4 switch
      • 2.2.5 数组
      • 2.2.6 切片
      • 2.2.7 map
      • 2.2.8 range
      • 2.2.9 函数
      • 2.2.10 指针
      • 2.2.11 结构体
      • 2.2.12 结构体方法
      • 2.2.13 错误处理
      • 2.2.14 字符串操作
      • 2.2.15 字符串格式化
      • 2.2.16 json处理
      • 2.2.17 时间处理
      • 2.2.18 数字解析
      • 2.2.19 进程信息
      • 三.本文总结

一.GO语言应用场景

这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天

1.1 前言

在学习GO语言的过程中会出一系类的go由浅入深的系列文章,敬请期待!

1.2 什么是GO语言

Go语言是一门现代编程语言,规则简单,统一,优雅,吸收了若干编程语言的优点,解决了C,C++, Python等语言一些固有的难点问题
Go是一种过程编程语言,可用于快速机器代码编译。它是一种静态类型的编译语言。它提供了并发机制,可以轻松开发多核和联网的机器级程序。它是快速,动态类型和解释语言;它提供对接口和类型嵌入的支持。

Go语言是由Google的Robert Griesemer,Rob Pike和Ken Thompson 于2007年开发,但于2009年作为开源编程语言推出。

注: go语言源代码文件的扩展名必须是.go 。
image-20230115155837088

GO语言的优点:

1高性能、高并发

2语法简单、学习曲线平缓

3丰富的标准库

Go具有强大的标准库,以包的形式分发。

4完善的工具链

5静态链接

Go是静态类型语言。因此,在这个编译器中,不仅可以成功编译代码,还可以确保类型转换和兼容性。由于这个特性,Go避免了我们在动态类型语言中遇到的所有问题。

6快速编译

7跨平台

Go语言就像Java语言一样,支持平台独立。由于其模块化设计和模块化,即代码被编译并转换为尽可能小的二进制形式,因此,它不需要依赖性。它的代码可以在任何平台上编译,也可以在任何服务器和应用程序上编译。

8垃圾回收

Go语言的设计者有意识地保持语言简单易懂。整个细节都在少量(一部分)页面中,并且通过语言中的面向对象支持做出了一些有趣的设计决策。对此,语言是固执的,并推荐一种实现事物的惯用方法。它更喜欢组合而不是继承。在Go语言中,“少花钱多办事”就是口头禅。

一个有开发经验的程序员,仅仅耗费一周就可以由学习阶段转到真正的开发阶段,完成一个高并发的应用开发。

1.3 仅仅10行完成高并发的服务器

如下图

image-20230115162850213

哪些公司在使用Go语言:

image-20230115195220871

二.入门

使用Goland,学生可以申请教育免费版:

image-20230115195539083

2.1 基础语法-HelloWorld

Hello World:

package main
​
import (
   "fmt"
)
​
func main() {
   fmt.Println("hello world,上进小菜猪")
}

上述代码解释:

package main:程序的入口包。入口文件

import 的fmt控制输入输出文件:

import ( “fmt” )

main函数调用了fmt的Println

运行结果:

image-20230115212323208

2.2 基础语法-变量类型

2.2.1 变量

声明变量:

1.使用var。

var a = "initial"
var b, c int = 1, 2
var d = true

2.使用变量名:=值。

f := float32(e)
g := a + "foo"

GO会更具上下文的类型来自动确定类型。

3.例子

引用:fmt和math

import (
   "fmt"
   "math"
)

main函数:

var a = "initial"
var b, c int = 1, 2
var d = true
var e float64
f := float32(e)
g := a + "foo"
fmt.Println(a, b, c, d, e, f) // initial 1 2 true 0 0
fmt.Println(g)                // initialapple
const s string = "constant"
const h = 500000000
const i = 3e20 / h
fmt.Println(s, h, i, math.Sin(h), math.Sin(i))

运行结果如下:

image-20230115213307712

2.2.2 if else

1.if后面不需要写括号的:例如

if 7%2 == 0 {
   fmt.Println("7 is even")
} else {
   fmt.Println("7 is odd")
}

2.import的简单写法:

import "fmt"

3.main函数:

if 7%2 == 0 {
   fmt.Println("7 is even")
} else {
   fmt.Println("7 is odd")
}
​
if 8%4 == 0 {
   fmt.Println("8 is divisible by 4")
}
​
if num := 9; num < 0 {
   fmt.Println(num, "is negative")
} else if num < 10 {
   fmt.Println(num, "has 1 digit")
} else {
   fmt.Println(num, "has multiple digits")
}

运行结果如下:

image-20230115213558122

2.2.3 循环

go里面只有for循环,没有while循环,没有do while循环。

简单的for循环如下:

for {
   fmt.Println("loop")
   break
}

可以使用经典的c语言里的for循环:

for j := 7; j < 9; j++ {
   fmt.Println(j)
}

也可以使用continue跳出循环:

for n := 0; n < 5; n++ {
   if n%2 == 0 {
      continue
   }
   fmt.Println(n)
}

运行结果如下:

image-20230115213906872

2.2.4 switch

分支结构和c、c++类似。

不同点:

c/c++如果没有break还会跑下面的同级分支,go则不会。

例子:

1.引入time时间库:

import (
   "fmt"
   "time"
)

2.源码:

先给a赋值为2,然后循环下面的值,运行fmt.Println(“two”),没有break语句也会跳出这个switch。

t := time.Now()使用time库,将现在的系统时间赋值给t,然后进行case条件分支,否则抛出It’s after noon。

a := 2
switch a {
case 1:
   fmt.Println("one")
case 2:
   fmt.Println("two")
case 3:
   fmt.Println("three")
case 4, 5:
   fmt.Println("four or five")
default:
   fmt.Println("other")
}
​
t := time.Now()
switch {
case t.Hour() < 12:
   fmt.Println("It's before noon")
default:
   fmt.Println("It's after noon")
}

运行结果如下:

image-20230115214430843

2.2.5 数组

先定义一个5个长度的数组,然后对第三个位置进行一个赋值,为100.

然后输出a[2]和a的数组长度。

var a [5]int
a[2] = 100
fmt.Println("get:", a[2])
fmt.Println("len:", len(a))

运行结果如下:

image-20230115215007486

定义数组的时候就给其赋值。然后输出b数组看一眼:

b := [5]int{1, 2, 3, 4, 5}
fmt.Println(b)

输出效果如下:

image-20230115215109857

二维数组:定义一个二维数组。使用双层循环对其赋值。

var twoD [2][3]int
for i := 0; i < 2; i++ {
   for j := 0; j < 3; j++ {
      twoD[i][j] = i + j
   }
}
fmt.Println("2d: ", twoD)

输出结果如下:

image-20230115215214038

2.2.6 切片

定义一个数组,指定其类型为字符。3个空间大小。然后对其进行赋值,然后输出第3个位置,和数组长度,代码如下:

s := make([]string, 3)
s[0] = "a"
s[1] = "b"
s[2] = "c"
fmt.Println("get:", s[2])   // c
fmt.Println("len:", len(s)) // 3

代码运行结果如下:

image-20230115230403180

数组追加,和pyrhon一样,使用append,但是注意,语法略微不同。

s = append(s, "d")
s = append(s, "e", "f")
fmt.Println(s) // [a b c d e f]

输出结果如下:

image-20230115230604748

数组的拷贝,使用copt函数,我们先创建一个空的c数组,申请一个大小。然后使用copy函数,将s数组拷贝到c数组。然后输出c数组查看一下效果:

c := make([]string, len(s))
copy(c, s)
fmt.Println(c) // [a b c d e f]

输出结果如下:

image-20230115230715940

切片:s[2:5]:第3个元素开始,到第5个之前(不包括第五个元素)

[:5]:开头到到第5个之前(不包括第五个元素)

s[2:]:第3个元素开始,到最后一个元素。代码如下:

fmt.Println(s[2:5]) // [c d e]
fmt.Println(s[:5])  // [a b c d e]
fmt.Println(s[2:])  // [c d e f]

输出结果如下:

image-20230115230850133

创建数组的时候,就进行赋值操作:

good := []string{"g", "o", "o", "d"}
fmt.Println(good) // [g o o d]

输出结果如下:

image-20230115230917979

2.2.7 map

创建一个map。使用make函数,键值对:string:int。对其进行赋值。

然后输出查看效果,打印长度。指定键,查看值。如下代码:

m := make(map[string]int)
m["one"] = 1
m["two"] = 2
fmt.Println(m)           // map[one:1 two:2]
fmt.Println(len(m))      // 2
fmt.Println(m["one"])    // 1
fmt.Println(m["unknow"]) // 0

输出结果如下:

image-20230115231225101

加入ok来看看是否有键存在。如下代码:

r, ok := m["unknow"]
fmt.Println(r, ok) // 0 false

输出结果如下:

image-20230115231400041

删除键值对。使用delete函数,代码如下。

delete(m, "one")

赋值案例:

m2 := map[string]int{"one": 1, "two": 2}
var m3 = map[string]int{"one": 1, "two": 2}
fmt.Println(m2, m3)

输出结果如下:

image-20230115231527585

2.2.8 range

for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。

首先定义一个numw数组,对其赋值。定义sum用于统计累加和。使用for 循环的 range 格式对其进行迭代循。具体如下:

nums := []int{2, 3, 4}
sum := 0
for i, num := range nums {
   sum += num
   if num == 2 {
      fmt.Println("index:", i, "num:", num) // index: 0 num: 2
   }
}
fmt.Println(sum) // 9

输出结果如下:

image-20230115232013611

for 循环的 range 格式对map的遍历案例如下:

m := map[string]string{"a": "A", "b": "B"}
for k, v := range m {
   fmt.Println(k, v) // b 8; a A
}
for k := range m {
   fmt.Println("key", k) // key a; key b
}

输出结果如下:

image-20230115232133944

2.2.9 函数

go语言的函数,有一些区别。变量名在后面。

先看一下主函数:

res := add(1, 2)
fmt.Println(res) // 3

然后看一下add函数,这个add函数的作用是返回俩个值相加的结果。

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

然后我们看一下返回多值的情况:

传入俩个参数,一个map,一个字符a。

v, ok := exists(map[string]string{"a": "A"}, "a")
fmt.Println(v, ok) // A True

看一下exists的函数。这里接受俩个函数,m[“a”]存在,ok的值为ture。返回给主函数。

func exists(m map[string]string, k string) (v string, ok bool) {
   v, ok = m[k]
   return v, ok
}

输出结果如下:

image-20230115233715973

2.2.10 指针

go语言的指针功能非常有限,主要的功能是为了对传入的参数进行修改。

这里的传入的参数实际上是一个拷贝。拷贝+1是不起作用的。

func add2(n int) {
   n += 2
}

想要起作用只能采用指针类型:

func add2ptr(n *int) {
   *n += 2
}

为了类型匹配,调用的时候,需要加&:add2ptr(&n)

下面是main函数:

n := 5
add2(n)
fmt.Println(n) // 5
add2ptr(&n)
fmt.Println(n) // 7

运行结果如下:

image-20230115235821740

2.2.11 结构体

先定义一个结构体user,定义两个变量:name和password:

type user struct {
   name     string
   password string
}

定义结构体值的几个方法:

下面代码是4种对结构体类型的赋值方法,非常简单。如下:

a := user{name: "wang", password: "1024"}
b := user{"wang", "1024"}
c := user{name: "wang"}
c.password = "1024"
var d user
d.name = "wang"
d.password = "1024"

输出来看一下:

fmt.Println(a, b, c, d)                 // {wang 1024} {wang 1024} {wang 1024} {wang 1024}

运行结果如下:

image-20230116000237471

使用函数:

普通函数(不使用指针。)

func checkPassword(u user, password string) bool {
   return u.password == password
}

使用指针:

func checkPassword2(u *user, password string) bool {
   return u.password == password
}

主函数,调用:

fmt.Println(checkPassword(a, "haha"))   // false
fmt.Println(checkPassword2(&a, "haha")) // false

运行结果如下:

image-20230116000429917

2.2.12 结构体方法

这里先把a赋值一个user结构体类型,并且对其进行赋值。

a := user{name: "wang", password: "1024"}
a.resetPassword("2048")

然后直接a.调用方法:

使用指针才能改变其结构体里的值。

func (u *user) resetPassword(password string) {
   u.password = password
}

检查一下结构体里的值是不是等于2048。

fmt.Println(a.checkPassword("2048")) // true

checkPassword函数的内容如下:

func (u user) checkPassword(password string) bool {
   return u.password == password
}

运行结果如下:

image-20230116001321360

2.2.13 错误处理

导入依赖包:errors,代码如下:

import (
   "errors"
   "fmt"
)

先看一下调用的findUser,我们先传入了应该数组,和一个字符串。

u, err := findUser([]user{{"wang", "1024"}}, "wang")

findUser如下:

这个函数作用是检查结构体的值,是不是我们规定的难搞值,如果是的话返回return &u, nil。否则就是出错了。返回return nil, errors.New(“not found”),将not found 写到日志里,代码如下:

func findUser(users []user, name string) (v *user, err error) {
   for _, u := range users {
      if u.name == name {
         return &u, nil
      }
   }
   return nil, errors.New("not found")
}

在主函数里,如果err不是nil的话,说明出错了,我们输出错误日志看一眼。

if err != nil {
   fmt.Println(err)
   return
}

输出u的name

fmt.Println(u.name) // wang

来一个错误案例:

我们调用findUser,但是传入 “li”,上面的代码当然会u.name != name,就会有日志存入,err,然后下面进入判断,输出err,代码如下:

if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil {
   fmt.Println(err) // not found
   return
} else {
   fmt.Println(u.name)
}

运行结果如下:

image-20230116002809804

2.2.14 字符串操作

导入依赖包:strings,代码如下:

import (
   "fmt"
   "strings"
)

方法列表:

image-20230116003152125

主函数代码,对字符串操作案例:

a := "hello"
fmt.Println(strings.Contains(a, "ll"))                // true
fmt.Println(strings.Count(a, "l"))                    // 2
fmt.Println(strings.HasPrefix(a, "he"))               // true
fmt.Println(strings.HasSuffix(a, "llo"))              // true
fmt.Println(strings.Index(a, "ll"))                   // 2
fmt.Println(strings.Join([]string{"he", "llo"}, "-")) // he-llo
fmt.Println(strings.Repeat(a, 2))                     // hellohello
fmt.Println(strings.Replace(a, "e", "E", -1))         // hEllo
fmt.Println(strings.Split("a-b-c", "-"))              // [a b c]
fmt.Println(strings.ToLower(a))                       // hello
fmt.Println(strings.ToUpper(a))                       // HELLO
fmt.Println(len(a))                                   // 5
b := "你好"
fmt.Println(len(b)) // 6

运行结果如下:

image-20230116003237960

2.2.15 字符串格式化

先分别定义一个字符串,整数,指针。分别打印一下,代码如下:

s := "hello"
n := 123
p := point{1, 2}
fmt.Println(s, n) // hello 123
fmt.Println(p)    // {1 2}

运行结果如下:

image-20230116003508388

可以使用任意%v来输出任意的的数值。代码如下:

可以使用%+v来输出详细的数值。

可以使用%#v来输出更加详细的数值。

\n标识换行。

fmt.Printf("s=%v\n", s)  // s=hello
fmt.Printf("n=%v\n", n)  // n=123
fmt.Printf("p=%v\n", p)  // p={1 2}
fmt.Printf("p=%+v\n", p) // p={x:1 y:2}
fmt.Printf("p=%#v\n", p) // p=main.point{x:1, y:2}

运行结果如下:

image-20230116003644089

小数,规定位数,这里和c/c++一模一样。

f := 3.141592653
fmt.Println(f)          // 3.141592653
fmt.Printf("%.2f\n", f) // 3.14

2.2.16 json处理

导入依赖包: “encoding/json”,代码如下:

import (
   "encoding/json"
   "fmt"
)

定义一个结构体userInfo。

type userInfo struct {
   Name  string
   Age   int `json:"age"`
   Hobby []string
}

对其进行一个赋值操作。

a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Golang", "TypeScript"}}

使用json的Marshal方法。我们先看一下Marshal方法:

func Marshal(v interface{}) ([]byte, error)

从返回值我们可以看到,该函数有两个返回值,一个是传入参数v的json编码,类型为[]byte,另外一个就是error。

将结构体变量a转换为json,代码如下:

buf, err := json.Marshal(a)

如果发送错误,输出错误日志:

if err != nil {
   panic(err)
}

我们如果直接输出的话,是一堆为编译的数字。我们输出需要将其转换为字符串(序列化)才能进行输出,代码如下:

fmt.Println(buf)         // [123 34 78 97...]
fmt.Println(string(buf)) // {"Name":"wang","age":18,"Hobby":["Golang","TypeScript"]} 

运行结果如下:

image-20230116005940222

使用MarshalIndent:

func MarshalIndent(v any, prefix, indent string)([]byte, error)

MarshalIndent 类似于 Marshal,但应用缩进来格式化输出。根据缩进嵌套,输出中的每个 JSON 元素都将在以前缀开头的新行开始,后跟一个或多个缩进副本。

buf, err = json.MarshalIndent(a, "", "\t")
if err != nil {
   panic(err)
}
fmt.Println(string(buf))

输出如下:

image-20230116010222214

JSON解码函数Unmarshal:

func Unmarshal(data []byte, v interface{}) error

Unmarshal函数解析json编码的数据并将结果存入v指向的值。

Unmarshal和Marshal做相反的操作,必要时申请映射、切片或指针,有如下的附加规则:

要将json数据解码写入一个指针,Unmarshal函数首先处理json数据是json字面值null的情况。此时,函数将指针设为nil;否则,函数将json数据解码写入指针指向的值;如果指针本身是nil,函数会先申请一个值并使指针指向它。

要将json数据解码写入一个结构体,函数会匹配输入对象的键和Marshal使用的键(结构体字段名或者它的标签指定的键名),优先选择精确的匹配,但也接受大小写不敏感的匹配。

var b userInfo
err = json.Unmarshal(buf, &b)
if err != nil {
   panic(err)
}
fmt.Printf("%#v\n", b) // main.userInfo{Name:"wang", Age:18, Hobby:[]string{"Golang", "TypeScript"}}

输出结果如下:

image-20230116010432616

2.2.17 时间处理

导入依赖包: “time”,代码如下:

import (
   "fmt"
   "time"
)

获取当前的时间并且输出:

now := time.Now()
fmt.Println(now) 

运行结果如下:

image-20230116010741028

还可以自己构造一个时间,如下代码:

t := time.Date(2022, 3, 27, 1, 25, 36, 0, time.UTC)
t2 := time.Date(2022, 3, 27, 2, 30, 36, 0, time.UTC)
fmt.Println(t)                                                  // 2022-03-27 01:25:36 +0000 UTC
fmt.Println(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute()) // 2022 March 27 1 25

然后进行一个输出,也可以指定输出年月日等等。代码运行结果截图如下:

image-20230116010915276

代码格式化:

fmt.Println(t.Format("2006-01-02 15:04:05"))     

我们指定输出格式,代码运行结果截图如下:

image-20230116011034079

时间差:使用sub函数,可以得出俩个时间的时间差。

diff := t2.Sub(t)
fmt.Println(diff)                           // 1h5m0s
fmt.Println(diff.Minutes(), diff.Seconds()) // 65 3900

代码运行结果截图如下:

image-20230116011128262

time.Parse()函数

Go语言中的Parse()函数用于解析格式化的字符串,然后查找它形成的时间值。

官方api:

func Parse(layout, value string) (Time, error)

在这里,layout通过以哪种方式显示参考时间(即定义为Mon Jan 2 15:04:05 -0700 MST 2006)来指定格式,如果它是该值的话。但是,先前定义的布局(例如UnixDate,ANSIC,RFC3339等)解释了标准时间以及参考时间的合适表示形式。并且value参数保存字符串。其中,从值中删除的元素假定为零,如果不可能为零,则假定为一。

返回值: 它返回它表示的时间值。并且如果不存在时区指示符,则它会返回UTC时间。

t3, err := time.Parse("2006-01-02 15:04:05", "2022-03-27 01:25:36")
if err != nil {
   panic(err)
}
fmt.Println(t3 == t)    // true

代码运行结果截图如下:

image-20230116011342067

时间戳:

fmt.Println(now.Unix()) // 1648738080

运行结果如下:

image-20230116011413986

2.2.18 数字解析

导入依赖包:“strconv”,代码如下:

import (
   "fmt"
   "strconv"
)

可以使用ParseFloa或者ParseInt转换小数或者整数。

f, _ := strconv.ParseFloat("1.234", 64)
    fmt.Println(f) // 1.234
​
n, _ := strconv.ParseInt("111", 10, 64)
    fmt.Println(n) // 111

上面代码整数的第二个参数代表转换数字的进制,这里是10进制。

如果是0的话就是自动转换。代码如下;

n, _ = strconv.ParseInt("0x1000", 0, 64)
fmt.Println(n) // 4096

使用Atoi快速把字符串转换为数字:

n2, _ := strconv.Atoi("123")
fmt.Println(n2) // 123

数字不合法处理:

n2, err := strconv.Atoi("AAA")
fmt.Println(n2, err) // 0 strconv.Atoi: parsing "AAA": invalid syntax

运行结果如下:

image-20230116011854083

2.2.19 进程信息

导入依赖包:“os"和"os/exec”,代码如下:

import (
   "fmt"
   "os"
   "os/exec"
)

输出命令行参数:

fmt.Println(os.Args)

获取或者写入环境变量:

fmt.Println(os.Getenv("PATH")) // /usr/local/go/bin...
fmt.Println(os.Setenv("AA", "BB"))

快速启动子进程,并且获得输入输出。

buf, err := exec.Command("grep", "127.0.0.1", "/etc/hosts").CombinedOutput()
if err != nil {
   panic(err)
}
fmt.Println(string(buf)) // 127.0.0.1       localhost

运行结果如下:image-20230116012325957

三.本文总结

本文写了下面几大块:

  • 什么是 G0语言
  • Go 语言基本特征
  • Go 语言应用优势
  • G0语言入门
  • 开发环境-安装 Golang
  • G0语言基础语法

下篇我将撰写Go语言的实战应用的笔记,敬请期待!

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

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

相关文章

Java基础之《netty(24)—netty入站与出站机制》

一、基本说明 1、netty的组件设计&#xff1a;netty的主要组件有Channel、EventLoop、ChannelFuture、ChannelHandler、ChannelPipe等。 2、ChannelHandler充当了处理入站和出站数据的应用程序逻辑的容器。 例如&#xff0c;实现ChannelInboundHandler接口&#xff08;或Chan…

开关电源详解

目录 电源分类 线性稳压电源&#xff08;LDO&#xff09; 适用场景 特点 基本组成 开关电源 适用场景 发展方向 特点 分类 基本组成&#xff1a; 开关电源和线性电源对比&#xff1a; 两款开关电源的性能参数对比&#xff1a; 某款电源适配器&#xff1a; 电源分类…

Python NumPy 拆分数组

前言NumPy&#xff08;Numerical Python的缩写&#xff09;是一个开源的Python科学计算库。使用NumPy&#xff0c;就可以很自然地使用数组和矩阵。NumPy包含很多实用的数学函数&#xff0c;涵盖线性代数运算、傅里叶变换和随机数生成等功能。本文主要介绍Python NumPy 拆分数组…

2-求和(蓝桥杯)

问题描述给定 nn 个整数 a_1, a_2, , a_na1,a2,⋅⋅⋅,an &#xff0c;求它们两两相乘再相加的和&#xff0c;即&#xff1a;Sa_{1} \cdot a_{2}a_{1} \cdot a_{3}\cdotsa_{1} \cdot a_{n}a_{2} \cdot a_{3}\cdotsa_{n-2} \cdot a_{n-1}a_{n-2} \cdot a_{n}a_{n-1} \cdot a_…

2022考研人年度总结,描摹23实习备战进行时

今年&#xff0c;是硝烟弥漫的一年在各个科目上努力也常常焦虑不断怀疑是否真的可以在考研的道路上每一件努力的小事看起来无所谓但却十分有必要2022考研热词是“努力” “披星戴月”“痛苦”你的每一个清晨与深夜都刻满了泪水与汗水春天你最爱期待夏天&#xff0c;夏天你说秋天…

JAVA开发运维(CI/CD)

CI :持续性集成CD&#xff1a;持续性部署SIT&#xff1a;系统集成测试UAT&#xff1a;用户验收测试研发流程的变化&#xff0c;因为用户永远一开始不知道自己想要什么样的东西&#xff0c;导致了软件无法从一而终的进行设计&#xff0c;用户需要能立刻运行的软件和功能。&#…

再学C语言36:指针和数组

指针提供了一种用来使用地址的符号方法&#xff0c;可以很有效地处理数组 数组标记实际上是一种变相使用指针的形式 数组名同时也是该数组首元素的地址&#xff0c;如果arr是一个数组&#xff0c;则&#xff1a; arr &arr[0]; 在C中&#xff0c;对一个指针加1的结果是…

【ROS】使用pluginlib自定义costmap地图层

文章目录 文章目录 前言 一、重写地图层 1.包含头文件 2.onInitialize() 3.updateBounds() 4.updateCosts() 二、向ROS注册 1.插件描述文件 2.向ROS注册插件 3.在costmap配置文件中使用 总结 前言 pluginlib是一个 C 库&#xff0c;用于从 ROS 包中加载和卸载插件。插件是从…

SpringBoot实战(十一)集成RebbitMQ

目录1.工作原理图1.1 配置阶段1.2 生产者1.3 消费者2.Maven依赖3.常用交换机类型3.1 direct 直连交换机3.2 fanout 广播交换机3.3 topic 主题交换机4.Direct 直连交换机4.1 yml配置4.2 配置类4.3 消息推送类4.4 消息监听类4.5 测试5.Fanout 广播交换机5.1 配置类5.2 消息推送类…

javascript画全年日历

前些日子闲聊群里有人提了用js画全年日历的需求&#xff0c;趁闲暇时间画了个小demo&#xff0c;下面还是先上效果图吧。 高亮显示的是今天的日期和标记要高亮显示的日期&#xff0c;也添加了点击事件的钩子&#xff0c;自己可以实现钩子函数&#xff0c;从而操作点击的日期值。…

综述 | 深度强化学习在自动驾驶中的应用

本文是2020年的综述论文《Deep Reinforcement Learning for Autonomous Driving: A Survey》的部分内容节选。翻译稿全文共2万6千字&#xff0c;本文略掉了第3、4节强化学习理论的介绍及扩展部分。摘要随着深度表征学习(deep representation learning)的发展&#xff0c;强化学…

【8】SCI易中期刊推荐——图像处理领域(中科院4区)

🚀🚀🚀NEW!!!SCI易中期刊推荐栏目来啦 ~ 📚🍀 SCI即《科学引文索引》(Science Citation Index, SCI),是1961年由美国科学信息研究所(Institute for Scientific Information, ISI)创办的文献检索工具,创始人是美国著名情报专家尤金加菲尔德(Eugene Garfield…

windows下Docker部署Flask的教程

Docker默认安装路径是在C盘&#xff0c;Windows中修改Docker**默认安装****路径方法&#xff1a; 1.先创建 D:\Program Files\Docker 目录 2.运行命令&#xff0c;创建链接 mklink /J "C:\Program Files\Docker" "D:\codeSoftware\Docker"3.点击exe安装…

logstash 向多目标输出多份日志输出syslog

logstash默认情况下是内置了输入syslog日志的&#xff0c;但是不支持输出syslog&#xff0c;需要输出syslog的情况下&#xff0c;就需要手动安装logstash-output-syslog插件。安装方法如下&#xff1a;下载logstash-output-syslog插件&#xff0c;https://rubygems.org/downloa…

SpringBoot 注册自己的Servlet(三种方式)

SpringBoot 注册自己的Servlet&#xff08;三种方式&#xff09; 目录SpringBoot 注册自己的Servlet&#xff08;三种方式&#xff09;方法1:使用servlet3.0规范提供的注解方式注册Servlet1,声明servlet及映射2&#xff0c;加上ServletComponentScan 才会扫描加了这个注解运行结…

LeetCode 62. 不同路径

&#x1f308;&#x1f308;&#x1f604;&#x1f604; 欢迎来到茶色岛独家岛屿&#xff0c;本期将为大家揭晓LeetCode 62. 不同路径&#xff0c;做好准备了么&#xff0c;那么开始吧。 &#x1f332;&#x1f332;&#x1f434;&#x1f434; 一、题目名称 LeetCode 62. …

蚂蚁智能内容合规产品,提供一站式营销合规管控解决方案

随着互联网服务的不断深化&#xff0c;产品营销的形式从传统文本、长图文&#xff0c;增加到短视频、直播等新媒介形态&#xff0c;展现形式愈加丰富的同时&#xff0c;也为营销宣传内容合规审核带来了诸多难题。如何解决与日俱增的审核量与合规审核人员有限之间的矛盾&#xf…

旧手机闲置?教你用Termux搭建个移动服务器

目录 前言 准备工作 实践 安装Termux&#xff1a; 运行Termux&#xff1a; 环境配置&#xff1a; 效果展示 写在最后 前言 最近偶然看到网上有人用KSWEB搭建本地服务器&#xff0c;于是突发奇想也想在手机中搭建一个node环境试试&#xff0c;趁着周末有空&#xff0c;…

Vue3商店后台管理系统设计文稿篇(五)

记录使用vscode构建Vue3商店后台管理系统&#xff0c;这是第五篇&#xff0c;主要记录Vue3项目路由知识 文章目录一、Vue3路由二、安装Element Plus三、NPM设置淘宝镜像四、Yarn 设置淘宝镜像正文内容&#xff1a; 一、Vue3路由 路由用于设定访问路径, 将路径和组件映射起来&…

【vue系列-06】vue的组件化编程

深入理解vue的组件一&#xff0c;vue组件1&#xff0c;什么是vue组件2&#xff0c;单文件组件和非单文件组件3&#xff0c;非单组件的基本使用4&#xff0c;vue组件命名规范4.1&#xff0c;一个单词组成4.2&#xff0c;多个单词组成5&#xff0c;组件与组件间的嵌套6&#xff0…