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

跟着实例学Go语言(二)

本教程全面涵盖了Go语言基础的各个方面。一共80个例子,每个例子对应一个语言特性点,非常适合新人快速上手。
教程代码示例来自go by example,文字部分来自本人自己的理解。

本文是教程系列的第二部分,共计20个例子、约1.2万字。

目录

  • 21. Interfaces
  • 22. Struct Embedding
  • 23. Generics
  • 24. Errors
  • 25. Goroutines
  • 26. Channels
  • 27. Channel Buffering
  • 28. Channel Synchronization
  • 29. Channel Directions
  • 30. Select
  • 31. Timeouts
  • 32. Non-Blocking Channel Operations
  • 33. Closing Channels
  • 34. Range over Channels
  • 35. Timers
  • 36. Tickers
  • 37. Worker Pools
  • 38. WaitGroups
  • 39. Rate Limiting
  • 40. Atomic Counters

21. Interfaces

下面的例子展示了用interface关键字定义接口。接口是一组方法签名的集合,用于实现多态。Go不像其他语言那样需要通过extend关键字显式指定类型的继承关系。如果一个struct类型实现了interface中定义的所有方法,那么就认为这个struct类型属于interface所定义的类型。传统的面向对象语言逻辑是:A is B if it’s a child of B;而Go的逻辑是:A is B if it acts like B。

package mainimport ("fmt""math"
)// 定义了interface:几何体,以及方法:计算面积、计算周长
// 定义顺序:type、interface名、interface
type geometry interface {area() float64perim() float64
}// 定义了struct:矩形和圆形,分别实现了geometry定义的所有接口
type rect struct {width, height float64
}
type circle struct {radius float64
}func (r rect) area() float64 {return r.width * r.height
}
func (r rect) perim() float64 {return 2*r.width + 2*r.height
}func (c circle) area() float64 {return math.Pi * c.radius * c.radius
}
func (c circle) perim() float64 {return 2 * math.Pi * c.radius
}func measure(g geometry) {fmt.Println(g)fmt.Println(g.area())fmt.Println(g.perim())
}func main() {r := rect{width: 3, height: 4}c := circle{radius: 5}// 矩形和圆形都可以作为几何体类型的参数传递measure(r)measure(c)
}
$ go run interfaces.go
{3 4}
12
14
{5}
78.53981633974483
31.41592653589793

22. Struct Embedding

下面的例子展示了结构体嵌套的做法。Go允许struct或者interface的嵌套使用,从而组合成更复杂的结构。这有点像Java中的外部类和内部类,外部结构和内部结构可以互相访问对方的字段和方法。这也可以看做是Go通过组合的方式来实现其他语言中的继承。

package mainimport "fmt"// 定义了基础类型
type base struct {num int
}func (b base) describe() string {return fmt.Sprintf("base with num=%v", b.num)
}// 定义了包装类型
type container struct {// 包装类型中包含了基础类型basestr string
}func main() {co := container{base: base{num: 1,},str: "some name",}// num变量可以被直接或间接访问fmt.Printf("co={num: %v, str: %v}\n", co.num, co.str)fmt.Println("also num:", co.base.num)fmt.Println("describe:", co.describe())type describer interface {describe() string}var d describer = cofmt.Println("describer:", d.describe())
}
$ go run struct-embedding.go
co={num: 1, str: some name}
also num: 1
describe: base with num=1
describer: base with num=1

23. Generics

泛型是Go 1.18版本引入的有争议但很有用的特性。泛型可以看做是类型参数,经常与map、slice等数据结构伴随使用。泛型用中括号表示,而不是其他语言中常用的尖括号。

package mainimport "fmt"// 泛型声明放在函数名后或者类型名后,可以为泛型参数指定要实现的接口名
func MapKeys[K comparable, V any](m map[K]V) []K {r := make([]K, 0, len(m))for k := range m {r = append(r, k)}return r
}type List[T any] struct {head, tail *element[T]
}type element[T any] struct {next *element[T]val  T
}func (lst *List[T]) Push(v T) {if lst.tail == nil {lst.head = &element[T]{val: v}lst.tail = lst.head} else {lst.tail.next = &element[T]{val: v}lst.tail = lst.tail.next}
}func (lst *List[T]) GetAll() []T {var elems []Tfor e := lst.head; e != nil; e = e.next {elems = append(elems, e.val)}return elems
}func main() {var m = map[int]string{1: "2", 2: "4", 4: "8"}fmt.Println("keys:", MapKeys(m))_ = MapKeys[int, string](m)lst := List[int]{}lst.Push(10)lst.Push(13)lst.Push(23)fmt.Println("list:", lst.GetAll())
}
$ go run generics.go
keys: [4 1 2]
list: [10 13 23]

24. Errors

Go提供了error和panic两种异常处理的方式。不同点在于,前者用于意料中的错误,通过函数返回值获取;后者用于意料外的严重错误,会中断程序执行,但可用recover捕捉恢复。Go建议对于一般错误,尽量使用error来处理。

package mainimport ("errors""fmt"
)func f1(arg int) (int, error) {if arg == 42 {// 使用errors.New()生成新的error,并作为第二个值返回return -1, errors.New("can't work with 42")}return arg + 3, nil
}type argError struct {arg  intprob string
}func (e *argError) Error() string {return fmt.Sprintf("%d - %s", e.arg, e.prob)
}func f2(arg int) (int, error) {if arg == 42 {return -1, &argError{arg, "can't work with it"}}return arg + 3, nil
}func main() {for _, i := range []int{7, 42} {if r, e := f1(i); e != nil {fmt.Println("f1 failed:", e)} else {fmt.Println("f1 worked:", r)}}for _, i := range []int{7, 42} {if r, e := f2(i); e != nil {fmt.Println("f2 failed:", e)} else {fmt.Println("f2 worked:", r)}}_, e := f2(42)if ae, ok := e.(*argError); ok {fmt.Println(ae.arg)fmt.Println(ae.prob)}
}
$ go run errors.go
f1 worked: 10
f1 failed: can't work with 42
f2 worked: 10
f2 failed: 42 - can't work with it
42
can't work with it

25. Goroutines

协程是Go的核心特性之一,它是一种轻量级的线程和任务调度机制,运行在操作系统级别的线程之上。它可以灵活地处理阻塞,从而减少大量异步代码的编写。我们可以开启大量的协程,而不用担心内存资源占用和线程上下文切换的代价。

package mainimport ("fmt""time"
)func f(from string) {for i := 0; i < 3; i++ {fmt.Println(from, ":", i)}
}func main() {f("direct")// 可以通过go执行函数来启动协程go f("goroutine")go func(msg string) {fmt.Println(msg)}("going")// 注意协程不会阻止主线程的结束,即使协程还未执行完。所以这里需要sleep 1秒time.Sleep(time.Second)fmt.Println("done")
}
$ go run goroutines.go
direct : 0
direct : 1
direct : 2
goroutine : 0
going
goroutine : 1
goroutine : 2
done

26. Channels

通道可用于在多个goroutine之间通信。发送方发送消息到通道中,接收方再从通道中接收消息。当使用非缓存通道时,发送和接收消息是同步操作,若有一方未完成都会造成对方阻塞。

package mainimport "fmt"func main() {// channel是引用类型,需要通过make创建messages := make(chan string)// 发送ping消息,并阻塞等待接收方go func() { messages <- "ping" }()// 接收ping消息,在接收到消息前阻塞msg := <-messagesfmt.Println(msg)
}
$ go run channels.go 
ping

27. Channel Buffering

缓冲通道可以支持异步发送,无需等待接收方响应。在创建时可指定最大缓冲队列大小,若队列中消息长度超过最大值,则发送还是会被阻塞。接收方无论是哪种情况,只要没有消息可以接收,就一定会被阻塞。

package mainimport "fmt"func main() {// 指定缓冲队列最大长度为2messages := make(chan string, 2)// 发送不再会被阻塞,因为有缓存队列messages <- "buffered"messages <- "channel"fmt.Println(<-messages)fmt.Println(<-messages)
}
$ go run channel-buffering.go 
buffered
channel

28. Channel Synchronization

Go鼓励通过通信的方式(CSP模型)实现同步,而非传统的共享内存。下面的例子展示了通过将主线程阻塞在接收端,从而保证goroutine先于主线程执行完。

package mainimport ("fmt""time"
)func worker(done chan bool) {fmt.Print("working...")time.Sleep(time.Second)fmt.Println("done")done <- true
}func main() {done := make(chan bool, 1)go worker(done)// 主线程阻塞在接收端,直至goroutine发送结束消息<-done
}
$ go run channel-synchronization.go      
working...done  

29. Channel Directions

通道在作为参数传递给函数时,可以指定通道的方向,函数内部只能按指定的方向发送或者接收数据。下面的例子展示了通过pings、pongs两个通道实现乒乓消息(先发送后回收)的效果。

package mainimport "fmt"// 先发送消息给pings
func ping(pings chan<- string, msg string) {pings <- msg
}// 再从pings中取消息,发送给pongs
func pong(pings <-chan string, pongs chan<- string) {msg := <-pingspongs <- msg
}func main() {pings := make(chan string, 1)pongs := make(chan string, 1)ping(pings, "passed message")pong(pings, pongs)// 最后从pongs中取消息fmt.Println(<-pongs)
}
$ go run channel-directions.go
passed message

30. Select

通过select可以实现在多个channel上等待。用法有点类似于网络通信中的select模型,只要有任意一个通道接收到数据,就可以从select中接触阻塞并读取这次到达的数据。

package mainimport ("fmt""time"
)func main() {c1 := make(chan string)c2 := make(chan string)go func() {// sleep 1秒,模拟耗时操作time.Sleep(1 * time.Second)c1 <- "one"}()go func() {time.Sleep(2 * time.Second)c2 <- "two"}()// 循环两次,保证从两个channel都读到数据for i := 0; i < 2; i++ {select {// 用select结合case实现多通道等待case msg1 := <-c1:fmt.Println("received", msg1)case msg2 := <-c2:fmt.Println("received", msg2)}}
}
$ time go run select.go 
received one
received tworeal    0m2.245s

31. Timeouts

超时可结合select使用,用于限制从channel获取消息的最大时间。

package mainimport ("fmt""time"
)func main() {c1 := make(chan string, 1)go func() {time.Sleep(2 * time.Second)c1 <- "result 1"}()select {case res := <-c1:fmt.Println(res)// 限制超时时间为1秒case <-time.After(1 * time.Second):fmt.Println("timeout 1")}c2 := make(chan string, 1)go func() {time.Sleep(2 * time.Second)c2 <- "result 2"}()select {case res := <-c2:fmt.Println(res)case <-time.After(3 * time.Second):fmt.Println("timeout 2")}
}
$ go run timeouts.go 
timeout 1
result 2

32. Non-Blocking Channel Operations

通常通道的发送和接收都是阻塞的。但是我们可以使用select和default来实现非阻塞操作,发送和接收都不再阻塞,而是在尝试失败后立即走default定义的默认逻辑。

package mainimport "fmt"func main() {messages := make(chan string)signals := make(chan bool)select {case msg := <-messages:fmt.Println("received message", msg)// 没有收到消息,不会阻塞,而是走default逻辑default:fmt.Println("no message received")}msg := "hi"select {case messages <- msg:fmt.Println("sent message", msg)// 没有接收方接收消息,不会阻塞,而是走default逻辑default:fmt.Println("no message sent")}select {case msg := <-messages:fmt.Println("received message", msg)case sig := <-signals:fmt.Println("received signal", sig)default:fmt.Println("no activity")}
}
$ go run non-blocking-channel-operations.go 
no message received
no message sent
no activity

33. Closing Channels

关闭通道后,通道不再允许发送消息。这时接收方读取完通道中所有消息后,得到结束信号,做通信结束的后续操作。

package mainimport "fmt"func main() {jobs := make(chan int, 5)done := make(chan bool)go func() {for {// 关闭channel且读完通道中所有消息后,more取到false,结束通信j, more := <-jobsif more {fmt.Println("received job", j)} else {fmt.Println("received all jobs")done <- truereturn}}}()for j := 1; j <= 3; j++ {jobs <- jfmt.Println("sent job", j)}// 用close函数关闭channelclose(jobs)fmt.Println("sent all jobs")// 用消息阻塞保证goroutine先于主线程执行完 <-done
}
$ go run closing-channels.go 
sent job 1
received job 1
sent job 2
received job 2
sent job 3
received job 3
sent all jobs
received all jobs

34. Range over Channels

使用range也可用于从通道接收消息,包括在已关闭的通道上。

package mainimport "fmt"func main() {queue := make(chan string, 2)queue <- "one"queue <- "two"close(queue)// 即使通道已关闭,仍然可以用range接收消息for elem := range queue {fmt.Println(elem)}
}
$ go run range-over-channels.go
one
two

35. Timers

定时器用于在将来的某个时间点执行代码。通过从通道接收到消息的方式表示达到触发时间点,接收到的消息为当前时间。

package mainimport ("fmt""time"
)func main() {// 用time.NewTimer()定义2秒后的定时器timer1 := time.NewTimer(2 * time.Second)// 阻塞在这里,直到到达触发时间点<-timer1.Cfmt.Println("Timer 1 fired")timer2 := time.NewTimer(time.Second)// 用goroutine的方式避免阻塞主线程go func() {<-timer2.Cfmt.Println("Timer 2 fired")}()// 用Stop()停止定时器stop2 := timer2.Stop()if stop2 {fmt.Println("Timer 2 stopped")}time.Sleep(2 * time.Second)
}
$ go run timers.go
Timer 1 fired
Timer 2 stopped

36. Tickers

周期定时器用于在将来周期性地执行某个任务,直至我们让它停下。

package mainimport ("fmt""time"
)func main() {// 定义了一个周期为500毫秒的周期定时器ticker := time.NewTicker(500 * time.Millisecond)done := make(chan bool)go func() {for {select {case <-done:return// 每间隔500毫秒从定时器通道接收到消息case t := <-ticker.C:fmt.Println("Tick at", t)}}}()// 1.6秒后停止定时器time.Sleep(1600 * time.Millisecond)ticker.Stop()done <- truefmt.Println("Ticker stopped")
}
$ go run tickers.go
Tick at 2012-09-23 11:29:56.487625 -0700 PDT
Tick at 2012-09-23 11:29:56.988063 -0700 PDT
Tick at 2012-09-23 11:29:57.488076 -0700 PDT
Ticker stopped

37. Worker Pools

工人池(协程池)用于使用固定数量的协程处理任务,防止协程数量太多。在部分特殊场景需要使用。协程池并非Go语言原生概念,而是基于已有语言特性搭建的开发模型。

package mainimport ("fmt""time"
)// worker从jobs通道获取任务,并将执行结果发送到results通道
func worker(id int, jobs <-chan int, results chan<- int) {for j := range jobs {fmt.Println("worker", id, "started  job", j)time.Sleep(time.Second)fmt.Println("worker", id, "finished job", j)results <- j * 2}
}func main() {const numJobs = 5jobs := make(chan int, numJobs)results := make(chan int, numJobs)// 开启worker数量为3的协程池for w := 1; w <= 3; w++ {go worker(w, jobs, results)}// 将新任务添加到jobs通道中for j := 1; j <= numJobs; j++ {jobs <- j}close(jobs)for a := 1; a <= numJobs; a++ {<-results}
}
$ time go run worker-pools.go 
worker 1 started  job 1
worker 2 started  job 2
worker 3 started  job 3
worker 1 finished job 1
worker 1 started  job 4
worker 2 finished job 2
worker 2 started  job 5
worker 3 finished job 3
worker 1 finished job 4
worker 2 finished job 5real    0m2.358s

38. WaitGroups

前面的例子展示了如何用通道实现主线程和单个goroutine之间的等待。下面将会展示如何使用WaitGroup实现对多个goroutine的等待。

package mainimport ("fmt""sync""time"
)func worker(id int) {fmt.Printf("Worker %d starting\n", id)time.Sleep(time.Second)fmt.Printf("Worker %d done\n", id)
}func main() {var wg sync.WaitGroupfor i := 1; i <= 5; i++ {// 对每个goroutine,等待计数加1wg.Add(1)i := igo func() {// 延迟执行,完成工作后,将等待计数减1defer wg.Done()worker(i)}()}// 当等待计数为0时,结束等待wg.Wait()}
$ go run waitgroups.go
Worker 5 starting
Worker 3 starting
Worker 4 starting
Worker 1 starting
Worker 2 starting
Worker 4 done
Worker 1 done
Worker 2 done
Worker 5 done
Worker 3 done

39. Rate Limiting

速率限制是互联网和软件工程中的概念,用于防止对资源的使用超过一定限度。Go通过周期定时器和通道可以方便地实现这一功能。

package mainimport ("fmt""time"
)func main() {requests := make(chan int, 5)for i := 1; i <= 5; i++ {requests <- i}close(requests)limiter := time.Tick(200 * time.Millisecond)for req := range requests {// 每200毫秒结束阻塞,接收一次请求<-limiterfmt.Println("request", req, time.Now())}burstyLimiter := make(chan time.Time, 3)// 先允许执行三次for i := 0; i < 3; i++ {burstyLimiter <- time.Now()}// 然后每200毫秒允许执行一次go func() {for t := range time.Tick(200 * time.Millisecond) {burstyLimiter <- t}}()burstyRequests := make(chan int, 5)for i := 1; i <= 5; i++ {burstyRequests <- i}close(burstyRequests)for req := range burstyRequests {<-burstyLimiterfmt.Println("request", req, time.Now())}
}
$ go run rate-limiting.go
request 1 2012-10-19 00:38:18.687438 +0000 UTC
request 2 2012-10-19 00:38:18.887471 +0000 UTC
request 3 2012-10-19 00:38:19.087238 +0000 UTC
request 4 2012-10-19 00:38:19.287338 +0000 UTC
request 5 2012-10-19 00:38:19.487331 +0000 UTCrequest 1 2012-10-19 00:38:20.487578 +0000 UTC
request 2 2012-10-19 00:38:20.487645 +0000 UTC
request 3 2012-10-19 00:38:20.487676 +0000 UTC
request 4 2012-10-19 00:38:20.687483 +0000 UTC
request 5 2012-10-19 00:38:20.887542 +0000 UTC

40. Atomic Counters

Go中的同步方式除了通过channel通信,还可以通过原子计数器。通过原子技术器访问或者修改数值变量,可以让这些操作成为原子性的。

package mainimport ("fmt""sync""sync/atomic"
)func main() {var ops uint64var wg sync.WaitGroupfor i := 0; i < 50; i++ {wg.Add(1)go func() {for c := 0; c < 1000; c++ {// 通过AddUnit64实现原子性增加,若是原子读取可用LoadUint64,注意这里需要传指针参数 atomic.AddUint64(&ops, 1)}wg.Done()}()}wg.Wait()fmt.Println("ops:", ops)
}
$ go run atomic-counters.go
ops: 50000

相关文章:

HCIP-Datacom-ARST必选题库_26_URPF【1道题】

一、单选 1.以下关于URPF(Unicast Reverse Path Forwarding)的描述,正确的是哪一项? 部署了严格模式的URPF,也能够可以同时部署允许匹配缺省路由模式 如果部署松散模式的URPE,默认情况下不需要匹配明细路由 如果部署松散模式的URPF,如果需要检查默认路由&#xff0c;则需要检…...

服务器端的图片一般存储在哪?

图片和其他静态文件通常存储在服务器的硬盘或 SSD 上&#xff0c;可能直接存储在本地&#xff0c;或通过网络文件系统&#xff08;如 NFS&#xff09;访问&#xff0c;也可能存储在专门的静态内容服务器或 CDN&#xff08;内容分发网络&#xff09;上。 图片服务器 那么这种专…...

【七】jmeter5.5+influxdb2.0+prometheus+grafana

参考文章&#xff1a;https://blog.csdn.net/wenxingchen/article/details/126892890 https://blog.csdn.net/Zuo19960127/article/details/119726652 https://blog.csdn.net/shnu_cdk/article/details/132182858 promethus参考 由于自己下载的是infuldb2.0&#xff0c;所以按照…...

Keil MDK6 使用标准库出现 error: no member named IP in NVIC_Type 原因和解决

出现错误: error: no member named IP in NVIC_Type131 | NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;| ~~~~ ^时间:2024-4-24 3:05 编辑器: vscode 扩展:Keil Studio Pack (MDK v6)packs:- pack: Keil::STM32F1xx_DFP@2.4.1- pack: ARM::CM…...

单链循环链表(初版

粗浅的设计了一个单向循环链表以及其功能的实现函数单向循环链表的定义 采用链式存储结构存储的顺序表 定义单向循环链表类型以及单向循环链表中的元素类型 定义单向链表中的元素类型 //指的是单向链表中的结点有效数据类型,用户可以根据需要进行修改 typedef int DataType_t…...

2024-04-23 闲话

2024-04-23 闲话郭军凯脱单之后,朋友圈频率大大提升。从一年一条提升到一个月一条了。前两天他把qq头像给换了(似乎现在微信头像也换了),因为我们三个人的qq群头像是三个人各自头像拼起来的,车昱辉点开qq给他雷击了一下。那天我正复习物理还是高代还是数分还是赶组会ddl忘…...

跟着实例学Go语言(二)

本教程全面涵盖了Go语言基础的各个方面。一共80个例子&#xff0c;每个例子对应一个语言特性点&#xff0c;非常适合新人快速上手。 教程代码示例来自go by example&#xff0c;文字部分来自本人自己的理解。 本文是教程系列的第二部分&#xff0c;共计20个例子、约1.2万字。 …...

linux+window+macos下的JDK安装

1. Linux中安装JDK &#xff08;1&#xff09;下载Linux版本的jdk压缩包 &#xff08;2&#xff09;解压 tar -zxvf 压缩包名 例如&#xff1a; tar -zxvf jdk-8u251-linux-x64.tar.gz&#xff08;3&#xff09;在系统配置文件配置java 编辑profile配置文件 vim /etc/prof…...

DiffuSEEG:一种基于stable diffusion 的SEEG数据补全方法

目录一. 立体脑电图&#xff08;SEEG&#xff09;1.1 SEEG概念1.2 SEEG作用1.3 SEEG的适用场景1.4 操作方法一. 立体脑电图&#xff08;SEEG&#xff09; 1.1 SEEG概念 立体脑电图&#xff08;SEEG&#xff09;&#xff1a;是一种借助外科微创的方法将电极植入到大脑不同的部…...

kubernetes—Service介绍

Service介绍 在kubernetes中&#xff0c;pod是应用程序的载体&#xff0c;我们可以通过pod的ip来访问应用程序&#xff0c;但是pod的ip地址不是固定的&#xff0c;这也就意味着不方便直接采用pod的ip对服务进行访问。 为了解决这个问题&#xff0c;kubernetes提供了Service资…...

AlphaFold2源码解析(7)--模型之Evoformer

AlphaFold2源码解析(7)–模型之Evoformer 这篇文章我们主要药讲解AlphaFold2的Evoformer的代码细节。 Evoformer Stack 该网络有一个双塔结构&#xff0c;在MSA堆栈中具有轴向的自我注意&#xff1b;在Pair堆栈中具有三角形的乘法更新和三角形的自我注意&#xff1b;以及外积…...

docker 安装 redis 6.0.8 cluster 实战 (3主3从) 动态扩容

这里将上篇博客搭建的3主3从 扩容为 4主4从 1. 新建两个node节点 docker run -d \ --net host \ --privileged \ --name redis-node-7 \ --log-opt max-size100m \ --log-opt max-file3 \ -v /root/docker/redis-node-7/data:/data \ redis:6.0.8 \ --cluster-enabled yes \ -…...

20221204

You are so much more than how you look. 你比你的外表更有魅力 Never give up until the fight is over. 永远不要放弃&#xff0c;要一直战斗到最后一秒。 whats done cannot be undone 覆水难收 If I was going somewhere, I was running。 如果我要去哪儿&#xff…...

CN_数据链路层流量控制@可靠的传输机制@ARP协议

文章目录流量控制技术(协议)停止-等待流量控制滑动窗口流量控制发送窗口接收窗口基本原理可靠的传输机制确认机制ACK超时重传机制RTOARQ处理差错自动重传请求ARQ协议&#x1f388;ARQ具体协议单帧ARQ协议停止-等待协议SW-ARQ例连续ARQ协议后退N帧协议(GBN)GBN多帧滑动窗口累计确…...

程序人生 | 与足球共舞的火柴人(致敬格拉利什,赋予足球更深的意义)

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;也会涉及到服务端 &#x1f4c3;个人状态&#xff1a; 在校大学生一枚&#xff0c;已拿多个前端 offer&#xff08;秋招&#xff09; &#x1f680;未…...

安装ubuntu20.04, CUDA11.4, cnDNN, tensorflow, pytorch

ubuntu22.04默认python为3.11 ubuntu20.04默认python为3.8 第一步&#xff0c;分区安装系统 efi引导区, 逻辑分区&#xff0c;512M root: 主分区&#xff0c;512M swap: 逻辑分区&#xff0c;64G home:逻辑分区&#xff0c;320G /:逻辑分区, 130G&#xff0c; CUDA是安装…...

shell脚本受限执行

shell 中运行的脚本或脚本的个代码断会禁用一些正常 shell 中可以执行的命令.这是限制脚本用户的权限和最小化运行脚本导致的破坏的安全措施.受限的内容包括&#xff1a;使用 cd 命令更改工作目录. 更改环境变量$PATH, $SHELL, $BASH_ENV,或$ENV 的值. 读或更改 shell 环境选项…...

HTTP 速查手册

一、通用身份验证 # 服务端返回401&#xff0c;并告知验证类型为Basic GET 401 Unauthorized WWW-Authenticate: Basic realm"description"# 浏览器输入验证信息后&#xff0c;请求头中携带验证信息 Authorization: Basic xxxxxxxxxx二、Cookie # 服务端返回set-co…...

【计算机视觉】 摄像机标定

摄像机标定 齐次坐标 齐次坐标&#xff0c;将欧氏空间的无穷远点&#xff0c;与投影空间中有实际意义的消失点&#xff0c;建立起映射关系。 把齐次坐标转化为笛卡尔坐标的方法&#xff1a;是前面n-1个坐标分量分别除以最后一个分量即可 一些解释和性质&#xff1a; 比较好的…...

【Redis】Redis安装步骤和特性以及支持的10种数据类型(Redis专栏启动)

&#x1f4eb;作者简介&#xff1a;小明java问道之路&#xff0c;专注于研究 Java/ Liunx内核/ C及汇编/计算机底层原理/源码&#xff0c;就职于大型金融公司后端高级工程师&#xff0c;擅长交易领域的高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。 &#x1…...

DHTMLX Diagram JavaScript/HTML5 Pro Library:5.0

Diagram — JavaScript/HTML5 Diagram Library Ω578867473 破解版DHTMLX Diagram comprises a set of interactive HTML5 UI components such as organization charts, flowcharts, decision trees, block diagrams, mind maps, etc. Consisting of nodes and connectors, di…...

GPS卫星位置解算

本文介绍了基于C语言的GPS卫星位置解算原理与程序设计。针对每个原理、公式、代码设计进行了详细讲解&#xff0c;希望能够给测绘学子们带来帮助。 参考书籍&#xff1a; 李征航 黄劲松&#xff1a;GPS测量与数据处理&#xff08;第三版&#xff09; 目录 基础原理 1&#xf…...

大数据:Sqoop 简介与安装

一、Sqoop 简介 Sqoop 是一个常用的数据迁移工具&#xff0c;主要用于在不同存储系统之间实现数据的导入与导出&#xff1a; 导入数据&#xff1a;从 MySQL&#xff0c;Oracle 等关系型数据库中导入数据到 HDFS、Hive、HBase 等分布式文件存储系统中&#xff1b; 导出数据&am…...

[附源码]计算机毕业设计文曦家教预约系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…...

HK1 BOX刷入 Armbian系统作为服务器

HK1 BOX刷入 Armbian系统作为服务器 1 安装Armbian到EMMC 硬件 HK1 BOX s905 x3 固件版本选择 Armbian_23.02.0_Aml_s905x3_bullseye_5.15.80_server_2022.12.01用usb启动&#xff0c;tf/sd有的设备不行&#xff0c;有干扰&#xff0c;有可能从TF卡无法启动系统。 用usb启…...

CEC2015:动态多目标野狗优化算法求解CEC2015(提供完整MATLAB代码,含GD、IGD、HV和SP评价指标)

一、动态多目标优化问题简介 现实世界中&#xff0c;许多优化问题不仅具有多属性&#xff0c;而且与时间相关&#xff0c;即随着时间的变化&#xff0c;优化问题本身也发生改变&#xff0c;这类问题称为动态多目标优化问题&#xff08;dynamic multi-objective optimization p…...

【蓝桥杯选拔赛真题31】python三位数组合个数 青少年组蓝桥杯python 选拔赛STEMA比赛真题解析

目录 python三位数组合个数 一、题目要求 1、编程实现 2、输入输出...

SpringBoot项目--如何不停服更新应用?

原文网址&#xff1a;SpringBoot项目--如何不停服更新应用&#xff1f;_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍Java后端项目如何不停机更新服务。 在生产环境中&#xff0c;一般都会每个服务部署多个实例。只要多于1个实例&#xff0c;就可以不停服更新应用。 不停服…...

MVVM与Vue响应式原理

Vue的响应式实现原理 MVVM M&#xff1a;模型 》data中的数据 V&#xff1a;视图 》模板 VM&#xff1a;视图模型 》Vue实例对象 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0EWNM16D-1670161519474)(C:\Users\lucas\Desktop\学习\图片\mode…...

vue和react的生命周期

vue和react的生命周期 一、Vue的生命周期二、React的生命周期2.1.类组件2.2.函数式组件一、Vue的生命周期 初始化阶段(组件创建、数据初始化)、挂载、更新、销毁 父子组件生命周期执行顺序 初次加载组件时:父beforeCreate – 父created – 父beforeMount – 子beforeCreate …...

浏览器高度兼容性

浏览器的卷去高度 1.标准模式 document.documentElement.scrollTop 2.非标准模式 document.body.scrollTop 浏览器高度兼容性 1.标准模式下 浏览器的实际高度&#xff1a; document.body.clientHeight 浏览器的可视高度&#xff1a;document.documentElement.clientHeight 2.非…...

关于天干地支及其计算

以天干地支计算日期是我国悠良的传统文化&#xff0c;最近在看如何计算人的生辰八字&#xff0c;写了个程序&#xff0c;但是只能算年的干支&#xff0c;月、日的干支计算方法太复杂了&#xff0c;望之只能却步&#xff0c;还是乖乖去查万年历比较好。这里记下关于干支的一些东…...

数据结构和算法之如何建立图

小白BG.1 邻接矩阵表示的图结点的结构 typedef struct GNode *PtrToGNode;//PtrToGNode是指向GNode的一个指针 struct GNode{ int Nv;//顶点数 int Ne;//边数 WeightType G[MaxVertexNum][MaxVertexNum]; DataType Data[MaxVertexNum];//存顶点的数据 }; typedef PtrToGNode MG…...

计算机毕业设计Java大众采编本微资讯发布平台(源码+系统+mysql数据库+lw文档)

计算机毕业设计Java大众采编本微资讯发布平台(源码系统mysql数据库lw文档) 计算机毕业设计Java大众采编本微资讯发布平台(源码系统mysql数据库lw文档)本源码技术栈&#xff1a; 项目架构&#xff1a;B/S架构 开发语言&#xff1a;Java语言 开发软件&#xff1a;idea eclipse…...

web前端-javascript-立即执行函数(说明、例子)

立即执行函数 /* (function(){alert("我是一个匿名函数~~~"); })(); */(function (a, b) {console.log("a " a);console.log("b " b); })(123, 456);1. 说明 函数定义完&#xff0c;立即被调用&#xff0c;这种函数叫做立即执行函数立即执…...

【计算机视觉】图像形成与颜色

图像形成与颜色 光照及阴影 辐射度学 颜色 颜色信息反映了入射光的能量分布与波长&#xff0c;可见光的波长在400nm到760nm之间。 RGB RGB分别代表三个基色&#xff08;R-红色、G-绿色、B-蓝色&#xff09;&#xff0c;如(0,0,0)表示黑色、(255, 255, 255)表示白色。其中2…...

Musical Christmas Lights——一个圣诞树灯光✨随音乐节奏改变的前端开源项目

文章目录前言视频介绍项目截图项目地址项目源码以上就是本篇文章的全部内容&#xff0c;将你编写好的项目分享给你的朋友们或者那个TA吧&#xff01;制作不易&#xff0c;求个三连&#xff01;❤️ &#x1f4ac; ⭐️前言 今天博主在刷短视频时&#x1f610;&#xff0c;朋友推…...

[附源码]Python计算机毕业设计SSM进出口食品安全信息管理系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…...

电平触发的触发器

普通的SR锁存器没有任何抗干扰能力 我们要加控制信号&#xff0c;来抵抗干扰 比如说我们不把信号直接加在门上&#xff0c;我们可以再加一级门电路&#xff0c;让这个输出和输入不在同一个门上&#xff0c;我们希望加入一个控制信号&#xff0c;来控制电路工作的时刻 对电路结…...

php后端+JQuery+Ajax简单表单提交

通过ajax,如果从后端直接想前端返回数组,那前端收到的是一个‘Array’的字符串。所以,我比较习惯的是用json对象的格式。由后端通过json_encode()函数,把数组封装成对象,传递到前端;前端也以json的格式接收。这里用提交表单来举例说明。 页面显示如下: JQueryAjax.…...

论文投稿指南——中文核心期刊推荐(计算机技术2)

>>>深度学习Tricks&#xff0c;第一时间送达<<< 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊。下面&#xff0c;简单介绍下什么是中文核心期刊要目总览&#xff1a; 《中文核心期刊要目总…...

集合java

java集合 集合、数组都是对多个数据进行存储操作的结构&#xff0c;简称Java容器 此时的存储&#xff0c;主要是指内存层面的存储&#xff0c;不涉及持久化的存储&#xff08;txt,jpg,avi&#xff09; Java集合可分为Collection 和 Map 两种体系 1. Collection接口&#xff1…...

spring boot 应用mybatis

Mybatis入门: Mybatis入门_做测试的喵酱的博客-CSDN博客 目录 一、spring boot 应用mybatis 核心 二、举例&#xff1a; 2.1 背景 2.2 项目结构&#xff1a; 2.3 依赖包 pom 2.4 项目配置文件application.yml 2.5 实例层entity 2.6 mybatis的mapper层 2.7 spring boot…...

Java项目:ssm图书馆管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 功能介绍 基于ssm的图书馆管理系统.主要功能包括&#xff1a;图书查询、图书管理、图书编辑、读者管理、图书的借阅与归还以及借还日志记录等。 用户分为…...

详解设计模式:命令模式

命令模式&#xff08;Command Pattern&#xff09;也被称为行动模式&#xff08;Action Pattern&#xff09;、事物模式&#xff08;Transaction Pattern&#xff09;&#xff0c;是在 GoF 23 种设计模式中定义了的行为型模式。 命令模式 是一种数据驱动的设计模式。请求以命令…...

家庭用户无线上网案例(AC通过三层口对AP进行管理)

组网需求 为一个家庭用户使用的网络架构。该家庭消费用户的上网流量大多是低速流量&#xff0c;例如浏览网页、玩游戏、看视频等。家庭成员使用的无线终端主要为手机、PC、电视机等。终端接入的数量正常情况下在10个以内&#xff0c;偶尔有家庭聚会等特殊情况&#xff0c;终端接…...

Spring Boot 2 (七):Spring Boot 如何解决项目启动时初始化资源

在我们实际工作中,总会遇到这样需求,在项目启动的时候需要做一些初始化的操作,比如初始化线程池,提前加载好加密证书等。今天就给大家介绍一个 Spring Boot 神器,专门帮助大家解决项目启动初始化资源操作。 这个神器就是 CommandLineRunner,CommandLineRunner 接口的 Co…...

用Hopper修改代理软件端口

背景 用代理软件可以访问google&#xff0c;但是端口经常不固定&#xff0c;从缺省1080变成了随机。 前几天其实已经用Hopper 3.0看了一次&#xff0c;但是好像不支持go&#xff0c;所以没反编译成功&#xff0c;这次换了4.0&#xff0c;支持了go。 Hopper与逆向 逆向的目的…...

PKI等介绍

PKI 1、概述 KPI名称&#xff1a;Public Key Infrastructure 公钥基础设施 KPI作用&#xff1a;通过加密技术和数字签名保证信息的安全 KPI组成&#xff1a;公钥加密技术、数字证书、CA、RA 2、信息安全三要素 机密型、完整型、身份验证、操作的不可否认性 3、哪些领域…...

《模拟电子技术》半导体原理部分笔记

《模拟电子技术》笔记绪论第一章 常用半导体器件第二章 基本放大电路绪论 有的人把三极管的出现作为电子技术工业革命的开始标志学习架构&#xff1a;半导体器件&#xff08;二极管、三极管、场效应晶体管&#xff09;、基于上述管的放大电路、集成运算放大器、放大电路的频率…...

Python与MySQL交互

第四章 Python与MySQL交互 1、客户端库概述及安装 PyMySQL介绍 PyMySQL是在 Python3.x 版本中用于连接 MySQL 服务器的一个客户端库。 PyMySQL安装&#xff1a; pip install pymysql执行过程如下图&#xff1a; [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来…...

list的模拟实现(万字解读+由浅入深)

先申明一下本篇总体介绍过程是按照逐步深入去写的&#xff0c;所以可能有些同样类型不在一块&#xff01; 前言&#xff1a; 写这篇博客的时候&#xff0c;我是边思考边写它&#xff01;自己其中感觉自己对于list的理解更加的深入&#xff0c;其中提出的很多问题让我明白了lis…...

Java项目:SSM CRM人事管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 CRM人事管理系统&#xff0c;主要功能有&#xff1a; 用户管理&#xff1a;用户查询、添加用户、编辑、删除&#xff1b; 职位管理&#xff1a…...

Qt+opencv 鼠标画线实现几何图形识别并动态创建

前言 使用Qt OpenCV实现&#xff0c;通过鼠标画线绘制几何图形&#xff0c;然后通过opencv进行图形轮廓识别&#xff0c;返回图形顶点&#xff0c;然后创建对应的几何图形添加到场景中。绘制使用QGraphics体系完成。 看效果图&#xff1a; 本文demo在这里 点击下载 环境: …...

HTML5期末大作业——HTML+CSS+JavaScript平遥古城旅游景点介绍(6页)

&#x1f468;‍&#x1f393;学生HTML静态网页基础水平制作&#x1f469;‍&#x1f393;&#xff0c;页面排版干净简洁。使用HTMLCSS页面布局设计,web大学生网页设计作业源码&#xff0c;这是一个不错的旅游网页制作&#xff0c;画面精明&#xff0c;排版整洁&#xff0c;内容…...

HTML5期末考核大作业 基于HTML+CSS+JavaScript沪上美食(9页)

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…...

【SAP ME 21】SAP ME创建开发组件(DC)resources

目录 1、说明 2、创建开发组件(DC) 3、相关性 4、公共部分 5、构建...

P1747 好奇怪的游戏

好奇怪的游戏 题目背景 《爱与愁的故事第三弹shopping》娱乐章。 调调口味来道水题。 题目描述 爱与愁大神坐在公交车上无聊&#xff0c;于是玩起了手机。一款奇怪的游戏进入了爱与愁大神的眼帘&#xff1a;***&#xff08;游戏名被打上了马赛克&#xff09;。这个游戏类似…...

开启智慧之旅,AI与机器学习驱动的微服务设计模式探索

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 &#x1f680; 转载自热榜文章&#x1f525;&#xff1a;探索设计模式的魅力&#xff1a;开启智慧…...

搜索文件1.0

案例1&#xff1a; 扫描指定目录&#xff0c;并找到名称中包含指定字符的所有普通文件&#xff08;不包含目录&#xff09;&#xff0c;并且后续询问用户是否要删除该文件 import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.util…...

K8S哲学 - probe 探针

探针分类&#xff1a; liveness probe readiness probe startup probe Liveness Probe&#xff1a;用于检查容器是否还在运行。如果 Liveness Probe 失败&#xff0c;Kubernetes 会杀死容器&#xff0c;然后根据你的重启策略来决定是否重新启动容器。常见的做法是使用与 Readin…...

前端工程搭建:

搭建前端工程最主要的是技术选型&#xff0c;如果技术选型不够全面或不合适&#xff0c;会出现很多问题。技术选型通常会涉及基础框架、打包构建工具、网络库、组件库、CSS预编译语言、状态管理、IDE、代码质量检查工具、包管理工具、版本控制工具等 CSS预编译语言 搭建工程没有…...