Golang——5、函数详解、time包及日期函数

news2025/6/8 3:24:01

函数详解、time包及日期函数

  • 1、函数
    • 1.1、函数定义
    • 1.2、函数参数
    • 1.3、函数返回值
    • 1.4、函数类型与变量
    • 1.5、函数作参数和返回值
    • 1.6、匿名函数、函数递归和闭包
    • 1.7、defer语句
    • 1.8、panic和recover
  • 2、time包以及日期函数
    • 2.1、time.Now()获取当前时间
    • 2.2、Format方法格式化输出日期字符串
    • 2.3、获取当前时间戳
    • 2.4、时间戳转换成日期字符串
    • 2.5、日期字符串转时间戳
    • 2.6、时间间隔和时间操作函数
    • 2.7、定时器

1、函数

1.1、函数定义

函数是组织好的、可重复使用的、用于执行指定任务的代码块。本文介绍了Go语言中函数的相关内容。
Go语言中支持:函数、匿名函数和闭包。
Go语言中定义函数使用 func 关键字,具体格式如下:

在这里插入图片描述

定义两个函数sumFn和subFn,分别对两个整数进行求和与差值。

package main

import "fmt"

func sumFn(x int, y int) int {
	res := x + y
	return res
}

func subFn(x int, y int) int {
	res := x - y
	return res
}

func main() {
	res1 := sumFn(10, 2)
	res2 := subFn(5, 3)
	fmt.Println(res1, res2)
}

在这里插入图片描述


1.2、函数参数

类型简写,函数的参数中如果相邻变量的类型相同,则可以省略类型,例如:
在这里插入图片描述

package main

import "fmt"

func sumFn(x, y int) int {
	return x + y
}

func main() {
	fmt.Println(sumFn(5, 10))
}

在这里插入图片描述

可变参数:可变参数是指函数的参数数量不固定。Go语言中的可变参数通过在参数名后加…来标识。
注意: 可变参数通常要作为函数的最后一个参数。

package main

import "fmt"

func sumFn(x ...int) {
	fmt.Printf("值: %v, 类型: %T\n", x, x)
}

func main() {
	sumFn(1, 2, 3, 4, 5)
}

在这里插入图片描述
可以看到可变参数x的类型是切片,因此我们可以遍历切片计算出总和。

package main

import "fmt"

func sumFn(x ...int) int {
	fmt.Printf("值: %v, 类型: %T\n", x, x)
	sum := 0
	for _, v := range x {
		sum += v
	}
	return sum
}

func main() {
	res := sumFn(1, 2, 3, 4, 5)
	fmt.Println(res)
}

在这里插入图片描述

固定参数搭配可变参数使用如下:

package main

import "fmt"

func sumFn(x int, y ...int) int {
	fmt.Printf("值: %v, 类型: %T\n", y, y)
	sum := x
	for _, v := range y {
		sum += v
	}
	return sum
}

func main() {
	res := sumFn(100, 1, 2, 3, 4)
	fmt.Println(res)
}

在这里插入图片描述


1.3、函数返回值

Go语言中通过return关键字向外输出返回值。
Go语言中函数支持多返回值,函数如果有多个返回值时必须用()将所有返回值包裹起来。

例如实现一个clac函数,既计算两数之和,也计算两数之差,返回两个返回值。

package main

import "fmt"

func clac(x, y int) (int, int) {
	sum := x + y
	sub := x - y
	return sum, sub
}

func main() {
	a, b := clac(10, 2)
	fmt.Println(a, b)
}

在这里插入图片描述

返回值命名:函数定义时可以给返回值命名,并在函数体中直接使用这些变量,最后通过return关键字返回。

package main

import "fmt"

func clac(x, y int) (sum, sub int) {
	sum = x + y
	sub = x - y
	return
}

func main() {
	a, b := clac(8, 3)
	fmt.Println(a, b)
}

在这里插入图片描述


将之前我们写的选择排序和冒泡排序实现成一个函数:

package main

import "fmt"

func SelectSort(arr []int) {
	for i := 0; i < len(arr); i++ {
		for j := i + 1; j < len(arr); j++ {
			if arr[i] > arr[j] {
				tmp := arr[i]
				arr[i] = arr[j]
				arr[j] = tmp
			}
		}
	}
}

func BubbleSort(arr []int) {
	for i := 0; i < len(arr); i++ {
		for j := 0; j < len(arr)-i-1; j++ {
			if arr[j] < arr[j+1] {
				tmp := arr[j]
				arr[j] = arr[j+1]
				arr[j+1] = tmp
			}
		}
	}
}

func main() {
	var sliceA = []int{11, 3, 213, 45, 63, 0, 10}
	SelectSort(sliceA)
	fmt.Println(sliceA)
	BubbleSort(sliceA)
	fmt.Println(sliceA)
}

在这里插入图片描述

下面实现一个函数将map类型数据按照key进行排序,把key=>value添加到字符串中返回。

package main

import (
	"fmt"
	"sort"
)

func mapSort(map1 map[string]string) string {
	var arr []string
	for k, _ := range map1 {
		arr = append(arr, k)
	}
	sort.Strings(arr)
	var res string
	for _, v := range arr {
		res += fmt.Sprintf("%v=>%v", v, map1[v])
	}
	return res
}

func main() {
	m1 := map[string]string{
		"username": "张三",
		"age":      "20",
		"sex":      "男",
		"height":   "180cm",
	}
	res := mapSort(m1)
	fmt.Println(res)
}

在这里插入图片描述

函数变量作用域:
全局变量:全局变量是定义在函数外部的变量,它在程序整个运行周期内都有效 (全局作用域)
局部变量:局部变量是函数内部定义的变量,函数内定义的变量无法在该函数外使用 (局部作用域)


1.4、函数类型与变量

定义函数类型:我们可以使用type关键字来定义一个函数类型,具体格式如下:
在这里插入图片描述
上面语句定义了一个calculation类型,它是一种函数类型,这种函数接收两个int类型的参数并且返回一个int类型的返回值。

package main

import "fmt"

type clac func(int, int) int
type myInt int

func add(x, y int) int {
	return x + y
}

func sub(x, y int) int {
	return x - y
}

func main() {
	var c clac
	c = add
	fmt.Printf("值: %v, 类型: %T\n", c, c)
	fmt.Println(c(3, 6))

	f := sub
	fmt.Printf("值: %v, 类型: %T\n", f, f)
	fmt.Println(f(10, 5))

	var a int = 10
	var b myInt = 20
	fmt.Printf("a的类型: %T, b的类型: %T\n", a, b)
	fmt.Println(a + int(b))
}

在这里插入图片描述
可以看到c的类型为main.clac,而f的类型则是func(int, int) int。另外a和b的类型也是不同的,所以相加时需要进行强转。


1.5、函数作参数和返回值

函数可以作为另一个函数的参数:

package main

import "fmt"

func add(x, y int) int {
	return x + y
}

func sub(x, y int) int {
	return x - y
}

type clacType func(int, int) int

func clac(x, y int, cb clacType) int {
	return cb(x, y)
}

func main() {
	res1 := clac(10, 5, add)
	res2 := clac(10, 5, sub)
	res3 := clac(10, 5, func(x, y int) int {
		return x * y
	})
	fmt.Println(res1, res2, res3)
}

在这里插入图片描述

对于前两个计算,我们传入了已有的函数add和sub。第三个计算我们传入了一个匿名函数,通俗来说就是没有名字的函数。

函数也可以作为返回值:

package main

import "fmt"

func add(x, y int) int {
	return x + y
}

func sub(x, y int) int {
	return x - y
}

type clacType func(int, int) int

func do(op string) clacType {
	switch op {
	case "+":
		return add
	case "-":
		return sub
	case "*":
		return func(x, y int) int {
			return x * y
		}
	default:
		return nil
	}
}

func main() {
	f1 := do("+")
	f2 := do("*")
	fmt.Println(f1(3, 4), f2(3, 4))
}

在这里插入图片描述


1.6、匿名函数、函数递归和闭包

匿名函数就是没有函数名的函数, 匿名函数的定义格式如下:
在这里插入图片描述
匿名函数因为没有函数名, 所以没办法像普通函数那样调用, 所以匿名函数需要保存到某个变量或者作为立即执行函数。

package main

import "fmt"

func main() {
	// 匿名自执行函数
	func() {
		fmt.Println("test...")
	}()

	var fn = func(x, y int) int {
		return x * y
	}
	fmt.Println(fn(3, 4))

	// 匿名自执行函数接收参数
	func(x, y int) {
		fmt.Println(x + y)
	}(3, 4)
}

在这里插入图片描述

函数内部可以再调用其他函数,也可以调用本函数,调用本函数就是函数递归。
比如,利用递归计算出1 + 2 + 3 + … + 100

package main

import "fmt"

func sum(x int) int {
	if x == 1 {
		return 1
	}
	return x + sum(x-1)
}

func main() {
	fmt.Println(sum(100))
}

在这里插入图片描述


全局变量的特点:常驻内存,污染全局。
局部变量的特点:不常住内存,不污染全局。
这里的污染全局就比如,在全局定义了一个变量a,在某个函数内容又定义了一个变量a,那么在访问的时候就会优先访问局部变量a。
闭包:可以让一个变量常驻内存且不污染全局。

闭包:
1、闭包是指有权访问另一个函数作用域中的变量的函数。
2、创建闭包的常见的方式就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。

如下:

package main

import "fmt"

func adder1() func() int {
	var x = 10
	return func() int {
		return x + 1
	}
}

func adder2() func(int) int {
	var x = 10
	return func(y int) int {
		x += y
		return x
	}
}

func main() {
	var fn1 = adder1()
	fmt.Println(fn1())
	fmt.Println(fn1())
	fmt.Println(fn1())

	fn2 := adder2()
	fmt.Println(fn2(10))
	fmt.Println(fn2(10))
	fmt.Println(fn2(10))
}

在这里插入图片描述
由于闭包里作用域返回的局部变量资源不会被立刻销毁回收,所以可能会占用更多的内存。过度使用闭包会导致性能下降,建议在非常有必要的时候才使用闭包。


1.7、defer语句

Go语言中的defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行,也就是说,先被 defer 的语句最后被执行,最后被defer的语句,最先被执行。

package main

import "fmt"

func main() {
	fmt.Println("开始")
	defer fmt.Println(1)
	defer fmt.Println(2)
	defer fmt.Println(3)
	fmt.Println("结束")
}

在这里插入图片描述
上面的中间三条打印语句被延迟执行了,并且执行的时候会逆序执行,有点像栈的结构特点。

package main

import "fmt"

func test() {
	fmt.Println("开始")
	defer func() {
		fmt.Println("aaa")
		fmt.Println("bbb")
	}()
	fmt.Println("结束")
}

func main() {
	test()
}

在这里插入图片描述


defer的执行时机:
在这里插入图片描述


defer在命名返回值和匿名返回函数中的表现不同。

package main

import "fmt"

func f1() int {
	var x = 0
	defer func() {
		x++
	}()
	return x
}

func f2() (x int) {
	defer func() {
		x++
	}()
	return x
}

func main() {
	fmt.Println(f1())
	fmt.Println(f2())
}

在这里插入图片描述
f1()的分析:
​​返回值机制​​:匿名返回值时,return x 实际上是将x的值(此时为0)​​复制到一个临时返回值变量​​中。
​​defer的执行​​:defer在return之后执行,修改的是局部变量x(从0→1),但​​临时返回值变量不受影响​​。
​​结果​​:函数返回临时变量存储的值0。

f2()的分析:
​​返回值机制​​:命名返回值时,x既是局部变量又是返回值变量。return x 直接返回x变量本身(此时值为0)。
​​defer的执行​​:defer在return之后执行,直接修改返回值变量x(从0→1)。
​​结果​​:函数返回被修改后的 x(值为 1)。


下面再来看一个例子,思考一下输出什么?

package main

import "fmt"

func f1() int {
	x := 5
	defer func() {
		x++
	}()
	return x
}

func f2() (x int) {
	defer func() {
		x++
	}()
	return 5
}

func f3() (y int) {
	x := 5
	defer func() {
		x++
	}()
	return x
}
func f4() (x int) {
	defer func(x int) {
		x++
	}(x) //defer注册要延迟执行的函数时该函数所有的参数都需要确定其值
	return 5
}

func main() {
	fmt.Println(f1())
	fmt.Println(f2())
	fmt.Println(f3())
	fmt.Println(f4())
}

f1()分析:
1、匿名返回值(未命名)
2、return x 将 x 的当前值 (5) 复制到​​临时返回值变量​​
3、defer 增加局部变量 x 的值 (5→6),但​​不影响临时返回值​​
4、返回临时变量的值 (5)

f2()分析:
1、命名返回值 x
2、return 5 等同于 x = 5
3、defer 直接修改返回值变量 x (5→6)
4、返回被修改后的x

f3()分析:
1、命名返回值 y
2、return x 等同于 y = x (将局部变量 x 的值 5 复制给 y)
3、defer 修改局部变量 x (5→6),但​​不影响返回值变量 y​​
4、返回 y (5)

f4()分析:
1、命名返回值 x
2、defer 接受参数时,​​参数值在注册时确定​​:
此时 x 还是初始零值 0(命名返回值初始化为0)
传入的 x 是值拷贝 (0)
3、return 5 将返回值变量 x 设为 5
4、defer 执行时,操作的是​​参数拷贝​​(0→1),不影响返回值变量 x
5、返回 x (5)


再来看另一个案例:

package main

import "fmt"

func calc(index string, a, b int) int {
	ret := a + b
	fmt.Println(index, a, b, ret)
	return ret
}

func main() {
	x := 1
	y := 2
	defer calc("AA", x, calc("A", x, y))
	x = 10
	defer calc("BB", x, calc("B", x, y))
	y = 20
}

在这里插入图片描述


1.8、panic和recover

在这里插入图片描述

Go 语言中目前是没有异常机制,但是可以使用panic/recover模式来处理错误。

package main

import "fmt"

func fn() {
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println("err:", err)
		}
	}()
	panic("抛出一个异常")
}

func main() {
	fn()
}

在这里插入图片描述

实现一个计算两数相除的函数,如果被除数为0,那么就会程序崩溃,这时候我们就可以使用defer + recover来处理,此时程序不会直接崩溃,会继续向后执行。

package main

import "fmt"

func div(x, y int) int {
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println("err:", err)
		}
	}()
	return x / y
}

func main() {
	fmt.Println(div(10, 0))
	fmt.Println(div(10, 2))
	fmt.Println(div(10, 5))
}

在这里插入图片描述


defer、panic、recover的配合使用:

package main

import (
	"errors"
	"fmt"
)

func readFile(fileName string) error {
	if fileName == "main.go" {
		return nil
	} else {
		return errors.New("读取文件失败")
	}
}

func myFn() {
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println("err:", err)
		}
	}()
	err := readFile("xxx.go")
	if err != nil {
		panic(err)
	}
}

func main() {
	myFn()
	fmt.Println("继续执行...")
}

在这里插入图片描述


2、time包以及日期函数

时间和日期是我们编程中经常会用到的,在golang中time包提供了时间的显示和测量用的函数。

2.1、time.Now()获取当前时间

package main

import (
	"fmt"
	"time"
)

func main() {
	timeObj := time.Now()
	fmt.Println(timeObj)
	year := timeObj.Year()
	month := timeObj.Month()
	day := timeObj.Day()
	hour := timeObj.Hour()
	minute := timeObj.Minute()
	second := timeObj.Second()
	fmt.Printf("%d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, minute, second)
}

在这里插入图片描述

2.2、Format方法格式化输出日期字符串

格式化的模板为Go的出生时间2006年1月2号15点04分。
2006->年
01->月
02->日
03->时, 03表示12小时制,15表示24小时制。
04->分
05->秒

package main

import (
	"fmt"
	"time"
)

func main() {
	timeObj := time.Now()
	str1 := timeObj.Format("2006-01-02 15:04:05")
	fmt.Println(str1)

	str2 := timeObj.Format("2006-01-02 03:04:05")
	fmt.Println(str2)
}

在这里插入图片描述


2.3、获取当前时间戳

时间戳是自1970年1月1日(08:00:00GMT)至当前时间的总秒数。 它也被称为Unix时间戳(UnixTimestamp)。

timeObj := time.Now()
unixtime := timeObj.Unix()
fmt.Println("当前时间戳:", unixtime)

unixNatime := timeObj.UnixNano()
fmt.Println("当前时间戳:", unixNatime)

在这里插入图片描述
Unix获取秒级别的时间戳,UnixNano获取纳秒级别的时间戳。


2.4、时间戳转换成日期字符串

unixTime := 1748842817
timeObj := time.Unix(int64(unixTime), 0)
var str = timeObj.Format("2006-01-02 15:04:05")
fmt.Println(timeObj)
fmt.Println(str)

在这里插入图片描述
使用time.Unix函数用于将时间戳转换成一个时间对象,第一个参数是int64的秒级时间戳,第二个参数是int64的纳秒级时间戳。


2.5、日期字符串转时间戳

func time.ParseInLocation(layout string, value string, loc *time.Location) (time.Time, error)

这是该函数的声明,第一个参数表示格式化模板,第二个参数表示要格式化的字符串,第三个参数传入time.Local即可,该函数有两个返回值,第一个返回值就是一个时间对象,然后我们通过这个事件对象调用Unix函数即可获取时间戳。

var str = "2025-06-03 09:00:00"
var tmp = "2006-01-02 15:04:05"
timeObj, _ := time.ParseInLocation(tmp, str, time.Local)
fmt.Println(timeObj)
fmt.Println(timeObj.Unix())

在这里插入图片描述


2.6、时间间隔和时间操作函数

time.Duration是time包定义的一个类型,它代表两个时间点之间经过的时间,以纳秒为单位。time.Duration表示一段时间间隔,可表示的最长时间段大约290年。
time 包中定义的时间间隔类型的常量如下:

const (
	Nanosecond Duration = 1
	Microsecond = 1000 * Nanosecond
	Millisecond = 1000 * Microsecond
	Second = 1000 * Millisecond
	Minute = 60 * Second
	Hour = 60 * Minute)
}

例如:time.Duration表示1纳秒,time.Second表示1秒。
上面的常量可以搭配时间操作函数来使用,例如Add函数的使用:

timeObj := time.Now()
fmt.Println(timeObj)
timeObj = timeObj.Add(time.Hour) // 增加一个小时
fmt.Println(timeObj)

在这里插入图片描述


2.7、定时器

1、使用time.NewTicker(时间间隔)来设置定时器。

ticker := time.NewTicker(time.Second)
n := 5
for t := range ticker.C {
	fmt.Println(t)
	n--
	if n == 0 {
		ticker.Stop()
		break
	}
}

在这里插入图片描述

2、time.Sleep(time.Second)实现定时器。

for i := 0; i < 5; i++ {
	fmt.Println("我正在执行定时任务...")
	time.Sleep(time.Second)
}

在这里插入图片描述

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

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

相关文章

深度学习环境配置指南:基于Anaconda与PyCharm的全流程操作

一、环境搭建前的准备 1. 查看基础环境位置 conda env list 操作说明&#xff1a;通过该命令确认Anaconda默认环境&#xff08;base&#xff09;所在磁盘路径&#xff08;如D盘&#xff09;&#xff0c;后续操作需跳转至该磁盘根目录。 二、创建与激活独立虚拟环境 1. 创…

打卡day46

知识点回顾&#xff1a; 不同CNN层的特征图&#xff1a;不同通道的特征图什么是注意力&#xff1a;注意力家族&#xff0c;类似于动物园&#xff0c;都是不同的模块&#xff0c;好不好试了才知道。通道注意力&#xff1a;模型的定义和插入的位置通道注意力后的特征图和热力图 内…

在SpringBoot中使用AWS SDK实现邮箱验证码服务

1.依赖导入&#xff08;maven&#xff09; <dependency><groupId>software.amazon.awssdk</groupId><artifactId>ses</artifactId><version>2.31.46</version></dependency> 2.申请两个key 发件人邮箱需要验证&#xff1a; …

深入理解二叉搜索树:原理到实践

1.二叉搜索树的概念 ⼆叉搜索树⼜称⼆叉排序树&#xff0c;它或者是⼀棵空树&#xff0c;或者是具有以下性质的⼆叉树 若它的左树不为空&#xff0c;则左子树上所有节点的值都小于或等于根节点的值。若它的右树不为空&#xff0c;则右子树上所有节点的值都大于或等于根节点的…

测试W5500的第11步_使用ARP解析IP地址对应的MAC地址

本文介绍了基于W5500芯片的ARP协议实现方法&#xff0c;详细阐述了ARP请求与回复的工作机制。ARP协议通过广播请求和单播回复实现IP地址与MAC地址的映射&#xff0c;确保局域网设备间的可靠通信。文章提供了完整的STM32F10x开发环境下的代码实现&#xff0c;包括网络初始化、SP…

终极数据结构详解:从理论到实践

终极数据结构详解&#xff1a;从理论到实践 我将从 底层原理、时间复杂度、空间优化、实际应用 和 代码实现 五个维度&#xff0c;彻底解析数据结构。内容涵盖&#xff1a; 线性结构&#xff08;数组、链表、栈、队列&#xff09;非线性结构&#xff08;树、图&#xff09;高…

【k8s】k8s集群搭建

k8s集群搭建 一、环境准备1.1 集群类型1.2 安装方式1.3 主机规划1.4 环境配置1.4.1 说明1.4.2 初始化1.4.3 关闭防火墙和禁止防火墙开机启动1.4.4 设置主机名1.4.5 主机名解析1.4.6 时间同步1.4.7 关闭selinux1.4.8 关闭swap分区1.4.9 将桥接的IPv4流量传递到iptables的链1.4.1…

60天python训练计划----day45

DAY 45 Tensorboard使用介绍 知识点回顾&#xff1a; tensorboard的发展历史和原理tensorboard的常见操作tensorboard在cifar上的实战&#xff1a;MLP和CNN模型 之前的内容中&#xff0c;我们在神经网络训练中&#xff0c;为了帮助自己理解&#xff0c;借用了很多的组件&#x…

C# Wkhtmltopdf HTML转PDF碰到的问题

最近碰到一个Html转PDF的需求&#xff0c;看了一下基本上都是需要依赖Wkhtmltopdf&#xff0c;需要在Windows或者linux安装这个可以后使用。找了一下选择了HtmlToPDFCore&#xff0c;这个库是对Wkhtmltopdf.NetCore简单二次封装&#xff0c;这个库的好处就是通过NuGet安装HtmlT…

Vue3 (数组push数据报错) 解决Cannot read property ‘push‘ of null报错问题

解决Cannot read property ‘push‘ of null报错问题 错误写法 定义变量 <script setup>const workList ref([{name:,value:}])</script>正确定义变量 <script setup>const workList ref([]) </script>解决咯~

html文字红色粗体,闪烁渐变动画效果,中英文切换版本

1. 代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>红色粗体闪烁文字表格 - 中英文切换</t…

基于Django开发的运动商城系统项目

运动商城系统项目描述 运动商城系统是一个基于现代Web技术构建的电子商务平台&#xff0c;专注于运动类商品的在线销售与管理。该系统采用前后端分离架构&#xff0c;前端使用Vue.js实现动态交互界面&#xff0c;后端基于Django框架提供RESTful API支持&#xff0c;数据库采用…

Python60日基础学习打卡Day45

之前的神经网络训练中&#xff0c;为了帮助理解借用了很多的组件&#xff0c;比如训练进度条、可视化的loss下降曲线、权重分布图&#xff0c;运行结束后还可以查看单张图的推理效果。 如果现在有一个交互工具可以很简单的通过按钮完成这些辅助功能那就好了&#xff0c;他就是…

【Visual Studio 2022】卸载安装,ASP.NET

Visual Studio 2022 彻底卸载教程 手动清理残留文件夹 删除C:\Program Files\Microsoft Visual Studio 是旧版本 Visual Studio 的残留安装目录 文件夹名对应的 Visual Studio 版本Microsoft Visual Studio 9.0Visual Studio 2008Microsoft Visual Studio 10.0Visual Studio…

thinkphp-queue队列随笔

安装 # 创建项目 composer create-project topthink/think 5.0.*# 安装队列扩展 composer require topthink/think-queue 配置 // application/extra/queue.php<?php return [connector > Redis, // Redis 驱动expire > 0, // 任务的过期时间…

STM32标准库-TIM输出比较

文章目录 一、输出比较二、PWM2.1简介2.2输出比较通道&#xff08;高级&#xff09;2.3 输出比较通道&#xff08;通用&#xff09;2.4输出比较模式2.5 PWM基本结构1、时基单元2、输出比较单元3、输出控制&#xff08;绿色右侧&#xff09;4、右上波形图&#xff08;以绿色脉冲…

科技创新驱动人工智能,计算中心建设加速产业腾飞​

在科技飞速发展的当下&#xff0c;人工智能正以前所未有的速度融入我们的生活。一辆辆无人驾驶的车辆在道路上自如地躲避车辆和行人&#xff0c;行驶平稳且操作熟练&#xff1b;刷脸支付让购物变得安全快捷&#xff0c;一秒即可通行。这些曾经只存在于想象中的场景&#xff0c;…

STM32H562----------ADC外设详解

1、ADC 简介 STM32H5xx 系列有 2 个 ADC,都可以独立工作,其中 ADC1 和 ADC2 还可以组成双模式(提高采样率)。每个 ADC 最多可以有 20 个复用通道。这些 ADC 外设与 AHB 总线相连。 STM32H5xx 的 ADC 模块主要有如下几个特性: 1、可配置 12 位、10 位、8 位、6 位分辨率,…

uniapp 安卓 APP 后台持续运行(保活)的尝试办法

在移动应用开发领域&#xff0c;安卓系统的后台管理机制较为复杂&#xff0c;应用在后台容易被系统回收&#xff0c;导致无法持续运行。对于使用 Uniapp 开发的安卓 APP 来说&#xff0c;实现后台持续运行&#xff08;保活&#xff09;是很多开发者面临的重要需求&#xff0c;比…

AI大数据模型如何与thingsboard物联网结合

一、 AI大数据与ThingsBoard物联网的结合可以从以下几个方面实现&#xff1a; 1. 数据采集与集成 设备接入&#xff1a;ThingsBoard支持多种通信协议&#xff08;如MQTT、CoAP、HTTP、Modbus、OPC-UA等&#xff09;&#xff0c;可以方便地接入各种物联网设备。通过这些协议&am…