Go:程序结构
文章目录
- 名称
- 声明
- 变量
- 短变量声明
- 指针
- new 函数
- 变量的生命周期
- 赋值
- 多重赋值
- 可赋值性
- 类型声明
- 包和文件
- 导入
- 包初始化
- 作用域
名称
命名规则:
- 通用规则:函数、变量、常量、类型、语句标签和包的名称,开头须是字母(Unicode 字符 )或下划线,后续可跟任意数量字符、数字和下划线,且区分大小写,如
heapSort
和Heapsort
是不同名称 。 - 关键字:Go 有 25 个关键字,如
break
、case
、func
等,只能用于语法规定处,不能作为名称 。
- 预声明名称:有一些预声明的常量(
true
、false
、iota
、nil
)、类型(int
、float32
、bool
、string
等 )和函数(make
、append
、len
等 ),这些名称虽可在声明中使用,但要注意冲突风险 。
可见性规则
- 函数内声明的实体仅在函数局部有效;函数外声明的实体对包内所有源文件可见 。名称首字母大小写决定其在包间的可见性,大写开头的名称是导出的,可被包外程序引用,如
fmt
包的Printf
;包名一般由小写字母组成 。
命名风格
- 长度:名称无长度限制,但习惯上,作用域小的局部变量倾向用短名称,如
i
;作用域大的使用长且有意义的名称 。 - 格式:Go 程序员常用 “驼峰式” 风格,由单词组合的名称用大写字母区分单词,如
QuoteRuneToASCII
,而非下划线分隔形式;首字母缩写词通常保持相同大小写 。
声明
声明的种类与作用
- 声明用于给程序实体命名并设定属性,Go 语言主要有变量(
var
)、常量(const
)、类型(type
)和函数(func
)这 4 种声明 。
程序结构中的声明顺序
- Go 程序由一个或多个
.go
文件组成,文件以package
声明开头表明所属包,接着是import
声明导入所需包,之后包级别的类型、变量、常量、函数声明顺序无严格要求 。
package mainimport "fmt"const boilingF = 212.0func main() {var f = boilingFvar c = (f - 32) * 5 / 9fmt.Printf("boiling point = %g°F or %g°C\n", f, c)
}
boiling
程序:展示了一个计算并输出水沸点(华氏温度和摄氏温度 )的程序 。const boilingF = 212.0
是包级常量声明 。包级声明在包内所有源文件可见,局部声明仅在声明所在函数内可见 。
func main() {const freezingF, boilingF = 32.0, 212.0fmt.Printf("%g°F = %g°C\n", freezingF, fToC(freezingF))fmt.Printf("%g°F = %g°C\n", boilingF, fToC(boilingF))
}func fToC(f float64) float64 {return (f - 32) * 5 / 9
}
ftoc
程序:实现华氏温度到摄氏温度的转换 。
变量
变量声明的形式
- 用
var
声明变量,通用形式为var name type = expression
,可省略类型或表达式之一,但不能都省略 。省略类型时,变量类型由初始化表达式决定;省略表达式时,变量初始值为对应类型零值 。如var s string
,s
初始值为空字符串 。
零值机制
- Go 语言中所有变量都有零值,数字为 0,布尔值为
false
,字符串为""
,接口和引用类型(切片、指针、映射、通道、函数 )为nil
,复合类型(数组、结构体 )零值是其元素或成员零值 。零值机制避免未初始化变量问题,简化代码 。
变量列表声明
- 可同时声明多个变量并初始化,如
var i, j, k int
声明三个int
类型变量,var b, f, s = true, 2.3, "four"
省略类型声明不同类型变量 。
变量初始化方式
- 初始值可以是字面量或任意表达式 。包级变量初始化在
main
函数开始前进行,局部变量在函数执行期间初始化 。还可通过调用返回多个值的函数初始化变量,如var f, err = os.Open(name)
,os.Open
返回文件和错误值 。
短变量声明
形式与原理
- 在函数中,短变量声明用
name := expression
形式声明和初始化局部变量 ,变量name
的类型由表达式expression
的类型决定 。如anim := gif.GIF{LoopCount: nframes}
,anim
类型由gif.GIF
结构体类型确定 。
适用场景与对比
- 因其简洁灵活,主要用于局部变量声明和初始化 。
var
声明则多用于变量类型与初始化表达式类型不一致,或初始值不重要、后续才赋值的情况 。
多个变量声明
- 可同时声明多个变量并初始化,如
i, j := 0, 1
,但要注意仅在对可读性有帮助时使用 ,比如for
循环初始化 。同时要区分:=
(声明 )和=
(赋值 ),避免与多重赋值混淆 。
调用多返回值函数
- 短变量声明可用于调用像
os.Open
这样返回多个值的函数,如f, err := os.Open(name)
,获取文件和错误值 。
注意事项
- 短变量声明不一定要声明所有左边变量,若已有变量在同一词法块中声明,新声明等同于赋值 。例如
in, err := os.Open(infile)
声明新变量,out, err := os.Create(outfile)
中err
已有声明则为赋值 。 - 短变量声明至少声明一个新变量,否则编译报错 ,如
f, err := os.Open(infile)
;f, err := os.Create(outfile)
(错误,无新变量 ) 。
指针
基本概念
- 定义:指针的值是变量的地址,可在不知变量名字时间接读取或更新变量值 。如变量
var x int
,&x
获取指向x
的指针,类型为*int
,指针p
指向x
时,*p
可获取或更新x
的值 。 - 零值与比较:指针类型零值是
nil
,测试p != nil
可判断指针是否指向变量 。两个指针仅在指向同一变量或都为nil
时相等 。
指针与变量
- 聚合类型变量(结构体成员、数组元素 )都是变量,有地址 。变量的表达式是唯一能应用取地址操作符
&
的表达式 。
函数与指针
- 返回局部变量指针:函数可返回局部变量地址,且局部变量在函数返回后依然存在,如
func f() *int
返回指向局部变量v
的指针 。 - 指针作为函数参数:传递指针参数给函数,能让函数更新间接传递的变量值 ,如
func incr(p *int) int
函数递增指针所指变量值并返回新值 。
在flag
包中的应用
指针在flag
包中很关键,用于通过命令行参数设置程序内变量值 。
var n = flag.Bool("n", false, "omit trailing newline")
var sep = flag.String("s", " ", "sparator")func main() {flag.Parse()fmt.Print(strings.Join(flag.Args(), *sep))if !*n {fmt.Println()}
}
实现:var n = flag.Bool("n", false, "omit trailing newline")
和var sep = flag.String("s", " ", "separator")
创建布尔和字符串标识变量,n
和sep
是指针,需通过*n
和*sep
访问 。运行程序时,先调用flag.Parse
更新标识变量默认值,非标识参数可从flag.Args()
获取 ,若flag.Parse
出错,程序输出帮助信息并以os.Exit(2)
结束 。
new 函数
功能与用法
new(T)
用于创建一个未命名的T
类型变量,初始化为T
类型的零值,并返回其地址(地址类型为*T
)。例如p := new(int)
,创建了一个未命名的int
类型变量,p
是指向该变量的指针,初始值为 0 ,后续可通过*p
操作该变量,如*p = 2
修改其值 。
与普通变量声明对比
- 用
new
创建的变量和普通局部变量取地址操作类似,只是无需为变量命名,属于语法上的便利,并非基础概念 。如func newInt() *int { return new(int) }
和func newInt() *int { var dummy int; return &dummy }
,二者功能相同 。
调用特性
- 每次调用
new
返回具有唯一地址的不同变量,如p := new(int); q := new(int); fmt.Println(p == q)
输出false
。但对于类型不携带信息且为零值的情况(如struct{}
或[0]int
),当前实现中它们地址相同 。
使用频率与重定义
- 因最常见未命名变量多为结构体类型,语法较复杂,所以
new
函数使用相对较少 。 new
是预声明函数,不是关键字,可在函数内重定义为其他类型,如func delta(old, new int) int { return new - old }
,但在此函数内,内置new
函数不可用 。
变量的生命周期
包级别变量:生命周期贯穿整个程序执行时间 。
局部变量:具有动态生命周期,每次执行声明语句时创建新实体,当变量变得不可访问时,其占用存储空间被回收 。函数参数和返回值也属于局部变量,在函数被调用时创建 。
垃圾回收与变量可达性
- 垃圾回收器通过追踪变量的引用路径判断是否回收变量 。包级别变量和当前执行函数的局部变量可作为追溯源头,若变量路径不存在即不可访问,就会被回收 。局部变量生命周期取决于其是否可达,即便包含它的循环结束,只要仍可达,就可能继续存在 。
变量的存储分配
- 编译器可选择在堆或栈上分配变量空间,此选择并非基于
var
或new
关键字 。
var global *int
func f() {var x intx = 1global = &x
}func g() {y := new(int)*y = 1
}
- 函数
f
中局部变量x
,因在函数返回后仍可通过global
变量访问(即从f
中逃逸 ),所以使用堆空间;而函数g
中用new
创建的变量*y
,在函数返回后不可访问,编译器可在栈上分配 。 - 理解变量逃逸概念对性能优化有帮助,变量逃逸需额外内存分配 。同时垃圾回收虽有助于编写正确程序,但要关注内存负担,了解变量生命周期对编写高效程序很重要,避免长生命周期对象持有短生命周期对象不必要的指针,影响垃圾回收 。
赋值
基本形式:赋值语句用于更新变量的值,最简形式由赋值符=
、左边变量和右边表达式组成 。多种赋值场景:
- 有名称变量:如
x = 1
,直接给变量x
赋值 。 - 间接变量(指针 ):
*p = true
,通过指针p
给其所指变量赋值 。 - 结构体成员:
person.name = "bob"
,给结构体person
的name
成员赋值 。 - 数组、切片或映射元素:
count[x] = count[x] * scale
,更新对应索引处元素值 。
赋值操作符
- 算术和二进制位操作符都有对应的赋值操作符,如
count[x] *= scale
等价于count[x] = count[x] * scale
,可避免表达式中重复书写变量 。
数字++和–
- 数字变量可通过
++
和--
进行递增递减操作 ,v++
等同于v = v + 1
,v--
等同于v = v - 1
。Go 中没有前置++
和--
,只有后置++
和--
,且无返回值。
多重赋值
概念:允许一次给多个变量赋值,在实际更新变量前,会先推演右边所有表达式 。
应用场景:
- 交换变量值:如
x, y = y, x
,可直接交换x
和y
的值;a[i], a[j] = a[j], a[i]
用于交换数组元素 。 - 计算最大公约数:在
gcd
函数中,for y != 0 { x, y = y, x%y }
,通过多重赋值不断更新x
和y
的值来计算最大公约数 。 - 计算斐波那契数列:
fib
函数里,for i := 0; i < n; i++ { x, y = y, x+y }
,利用多重赋值迭代计算斐波那契数列第n
个数 。 - 紧凑赋值序列:如
i, j, k = 2, 3, 5
,可一次性给多个变量赋值 。
注意:从风格上,若表达式复杂,建议避免使用多重赋值,用独立语句更易读 。当赋值语句中使用有多个返回值的函数调用时,左边变量个数要与函数返回值个数一致,如f, err = os.Open("foo.txt")
。
特殊情况:
- 函数常通过额外返回值指示错误等情况 。
- 一些操作(map 查询、类型断言、通道接收 )在赋值语句中会产生额外布尔型结果,如
v, ok = m[key]
(map 查询 )、v, ok = x.(T)
(类型断言 )、v, ok = <-ch
(通道接收 ) 。 - 如同变量声明,可将不需要的值赋给空白标识符
_
,如_, err = io.Copy(dst, src)
(丢弃字节个数 )、_, ok = x.(T)
(检查类型但丢弃结果 ) 。
可赋值性
- 显式赋值:通过赋值语句(如
x = 1
)进行的赋值操作 。 - 隐式赋值:函数调用时将参数值赋给对应参数变量、
return
语句将操作数赋给结果变量,以及复合类型字面量表达式对元素的赋值(如medals := []string{"gold", "silver", "bronze"}
,等同于medals[0] = "gold"; medals[1] = "silver"; medals[2] = "bronze"
) 。map
和通道元素也有类似隐式赋值 。
可赋值性规则
- 无论是隐式还是显式赋值,当左边变量和右边值的类型相同时,赋值合法 ,即值对于变量类型可赋值时才合法 。对于已讨论类型,类型需精准匹配,
nil
可赋给任何接口变量或引用类型 。常量有更灵活可赋值性规则以避免显式转换 。
与比较操作的关系
- 两个值用
==
和!=
比较时,与可赋值性相关,比较中第一个操作数相对于第二个操作数的类型必须是可赋值的,或可反向赋值 ,后续引入新类型时会解释其可比较性规则 。
类型声明
-
概念:用
type
声明定义新的命名类型,与某个已有类型使用相同底层类型 ,形式为type name underlying - type
。 -
作用:区分底层类型的不同使用场景,避免混淆 。例如,在温度转换程序中,定义
type Celsius float64
和type Fahrenheit float64
,虽底层类型都是float64
,但分别代表摄氏温度和华氏温度,防止不同计量单位温度值的无意合并 。 -
类型转换操作:每个类型
T
都有对应的类型转换操作T(x)
,将值x
转换为类型T
。如Celsius(t)
和Fahrenheit(t)
是类型转换,不会改变值和表达方式,仅改变显式意义 。 -
类型转换规则:具有相同底层类型或指向相同底层类型变量的未命名指针类型可相互转换,且不改变值的表达方式 。数字类型、字符串和一些切片类型间转换会改变值的表达方式,如浮点型转整型会丢失小数部分 ,但运行时转换不会失败 。
比较与操作
- 命名类型的值可与其相同类型的值或底层类型相同的未命名类型的值,通过
==
和<
等比较操作符进行比较 ,不同命名类型的值不能直接比较 。 - 命名类型可使用与底层类型相同的算术操作符 ,如
Celsius
和Fahrenheit
类型可进行与float64
相同的算术运算 。
类型的方法关联
- 以
Celsius
类型为例,可声明关联方法,如func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) }
,当通过fmt
包输出变量时,可控制类型值的显示方式 。
包和文件
- 作用:类似于其他语言的库或模块,用于支持模块化、封装、编译隔离和重用 。
- 概念:包的源代码存于一个或多个
.go
文件,所在目录名尾部是包的导入路径 。包为声明提供独立命名空间,不同包中同名函数互不干扰 。通过控制标识符是否以大写字母开头,管理其对外可见性(导出标识符大写开头 ) 。
包的示例
package tempconvimport "fmt"type Celsius float64
type Fahrenheit float64const (AbsoluteZeroC Celsius = -273.15FreezingC Celsius = 0BoilinfC Celsius = 100
)func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) }
func (f Fahrenheit) String() string { return fmt.Sprintf("%g°F", f) }
package tempconvfunc CToF(c Celsius) Fahrenheit { return Fahrenheit(c * 9 / 5 + 32)}func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9)}
以温度转换功能创建gopl.io/ch2/tempconv
包为例:
- 文件构成:包内有
tempconv.go
和conv.go
两个文件 。tempconv.go
声明了Celsius
和Fahrenheit
类型、相关常量,以及类型的String
方法 ;conv.go
包含温度转换函数CTOF
和FTOC
。 - 包的使用:每个文件开头用
package
声明包名 。导入包后,可通过包名.成员名
方式引用包内成员,如tempconv.CToF
。包级常量若大写开头,也可通过修饰名(如tempconv.AbsoluteZeroC
)访问 。 - 文档注释:包声明前应紧跟文档注释描述整个包,习惯在开头用一句话总结,一个包通常只有一个文件含文档注释,扩展注释一般放于名为
doc.go
的文件中 。
导入
概念
- 在 Go 程序中,每个包通过导入路径(import path )这一唯一字符串标识,如
"gopl.io/ch2/tempconv"
。语言规范未定义其来源和含义,由工具解释 。导入路径标注目录,该目录含包的.go
源文件 。包名通常与导入路径最后一段匹配,如gopl.io/ch2/tempconv
包名是tempconv
。
示例
package mainimport ("fmt""os""strconv""gopl.io/ch2/tempconv"
)func main() {for _, arg := range os.Args[1:] {t, err := strconv.ParseFloat(arg, 64)if err != nil {fmt.Fprintf(os.Stderr, "cf: %v\n", err)os.Exit(1)}f := tempconv.Fahrenheit(t)c := tempconv.Celsius(t)fmt.Printf("%s = %s, %s = %s\n",f, tempconv.FToC(f), c, tempconv.CToF(c))}
}
- 以
cf
程序为例,它导入"gopl.io/ch2/tempconv"
包,将命令行参数转换为摄氏温度和华氏温度 。在main
函数中,遍历命令行参数,先将参数转换为浮点数,再分别转换为Fahrenheit
和Celsius
类型,最后输出转换后的温度值 。 - 导入声明可给导入的包绑定短名字(默认是包名 ),用于在文件中引用包内容,如
tempconv.CToF
。也可设定可选名字避免冲突 。
检查机制
- 若导入包但未在代码中引用,会触发错误,这有助于消除不再需要的依赖 。如调试时注释掉对包唯一引用的代码,会导致编译器报错,此时需注释或删除不必要的
import
。
包初始化
变量
- 包的初始化从包级变量开始,变量按声明顺序初始化,在依赖解析完成后,依据依赖顺序进行 。例如
var a = b + c
、var b = f()
、var c = 1
、func f() int { return c + 1 }
,先初始化c
为 1 ,再调用f
初始化b
为 2 ,最后初始化a
为 3 。若包由多个.go
文件组成,初始化按编译器接收文件顺序进行(go
工具会在调用编译器前对文件排序 ) 。
init
函数
- 对于一些初始化表达式不只是简单设置初始值的变量(如数据表 ),可使用
init
函数 。任何文件可包含任意数量init
函数,其不能被调用或引用,在程序启动时,按声明顺序自动执行 。 - 包的初始化按导入顺序进行,依赖顺序优先,被导入包先完成初始化 ,
main
包最后初始化 ,确保在main
函数执行前所有包初始化完毕 。
示例
package popcountvar pc [256]bytefunc init() {for i := range pc {pc[i] = pc[i / 2] + byte(i&1)}
}func Popcount(x uint64) int {return int(pc[byte(x >> (0 * 8))] +pc[byte(x >> (1 * 8))] +pc[byte(x >> (2 * 8))] +pc[byte(x >> (3 * 8))] +pc[byte(x >> (4 * 8))] +pc[byte(x >> (5 * 8))] +pc[byte(x >> (6 * 8))] +pc[byte(x >> (7 * 8))])
}
- 以
popcount
包为例,定义了PopCount
函数用于统计uint64
值中置位个数 。通过init
函数预先计算结果表pc
,PopCount
函数利用该表计算,避免 64 步计算 。init
函数中for i := range pc
循环只使用索引,也可写成for i, _ := range pc
。
作用域
与生命周期的区别
-
声明的作用域是在程序文本中声明名字出现的区域,是编译时属性;变量的生命周期是变量在程序执行期间能被引用的起止时间,是运行时属性 。
-
语法块:由大括号包围的语句序列,如循环体、函数体等,内部声明变量对外不可见 。
-
词法块:可推广到没显式大括号包含的声明代码,包括全局块(含全部源代码 )、包、文件、
for
、if
、switch
语句及switch
和select
语句中的条件部分 。显式大括号代码块也属词法块 。
作用域规则
- 声明的词法块决定其作用域大小 。内置类型、函数、常量在全局块声明,对整个包可见,可在包内任何文件引用 。包级声明在包内文件可见 ,局部声明(如函数内变量声明 )仅在声明所在函数或部分语句内可用 。控制流标签(
break
、continue
、goto
使用的标签 )作用域是外层函数 。 - 不同词法块可声明同名实体 ,但要避免滥用 。编译器从最内层封闭词法块到全局块查找名字声明,若未找到报 “undeclared name” 错误,内层声明会覆盖外层 。
词法块嵌套与变量作用域
- 函数内词法块嵌套深,局部变量声明可能覆盖其他声明 。如
for
循环创建显式和隐式词法块,隐式词法块中声明变量作用域包括条件、后置语句及循环体本身 。if
和switch
语句也会创建隐式词法块,条件对应一个块,每个case
语句体对应一个块 ,且隐式词法块中初始化部分声明变量在后续语句可能不可见 。
包级别声明与作用域
- 包级别声明顺序和作用域无关,可引用自身或后面声明(如递归类型和函数 ),但常量或变量声明引用自身会报错 。同时局部变量在
if
语句中作用域相关编译错误及解决办法 ,短变量声明对作用域的依赖 。
var cwd string
func init() {// cwd, err := os.Getwd() // 错误var err errorcwd, err = os.Getwd() // 正确// ...
}
for
循环创建显式和隐式词法块,隐式词法块中声明变量作用域包括条件、后置语句及循环体本身 。if
和switch
语句也会创建隐式词法块,条件对应一个块,每个case
语句体对应一个块 ,且隐式词法块中初始化部分声明变量在后续语句可能不可见 。
包级别声明与作用域
- 包级别声明顺序和作用域无关,可引用自身或后面声明(如递归类型和函数 ),但常量或变量声明引用自身会报错 。同时局部变量在
if
语句中作用域相关编译错误及解决办法 ,短变量声明对作用域的依赖 。
var cwd string
func init() {// cwd, err := os.Getwd() // 错误var err errorcwd, err = os.Getwd() // 正确// ...
}
参考资料:《Go程序设计语言》
相关文章:
Go:程序结构
文章目录 名称声明变量短变量声明指针new 函数变量的生命周期 赋值多重赋值可赋值性 类型声明包和文件导入包初始化 作用域 名称 命名规则: 通用规则:函数、变量、常量、类型、语句标签和包的名称,开头须是字母(Unicode 字符 &a…...
sqlserver2017 分离附加数据库
分离数据库 分离数据库是指将数据库从 SQL Server 实例中移除,但会完整保留数据库及其数据文件和事务日志文件。 然后可以使用这些文件将数据库附加到任何 SQL Server 实例,包括分离该数据库的服务器。 如果存在下列任何情况,则不能分离数据…...
QuarkPi-CA2 RK3588S卡片电脑:6.0Tops NPU+8K视频编解码+接口丰富,高性能嵌入式开发!
QuarkPi-CA2 RK3588S卡片电脑:6.0Tops NPU8K视频编解码接口丰富,高性能嵌入式开发! 芯片框架 视频介绍 https://www.bilibili.com/video/BV1btdbYkEjY 开发板介绍 核心升级,产品炸裂 QuarkPi-CA2卡片电脑搭载瑞芯微RK3588S芯片…...
对称加密与非对称加密与消息摘要算法保证https的数据交互的完整性和保密性
一、对称加密与非对称加密的作用 1. 对称加密 作用: 保密性:对称加密使用相同的密钥对数据进行加密和解密,确保数据在传输过程中不被窃听。效率:对称加密算法(如AES)计算速度快,适合加密大量数…...
Lab Cloud FPGA 硬件在线实验云平台介绍
友晶科技依托其在FPGA技术领域的深厚积累,成功研发出了一套完整的FPGA云平台解决方案(即FPGA 硬件在线实验云,简称LabCloud )。LabCloud 是一个高效、实用的学习平台,目前已在多个学校成功部署。 LabCloud 是通过 B/S …...
相机回调函数为静态函数原因
在注册相机SDK的回调函数时,是否需要设置为静态函数取决于具体SDK的设计要求,但通常需要遵循以下原则: 1. 必须使用静态函数的情况 当相机SDK是C语言接口或要求普通函数指针时,回调必须声明为静态成员函数或全局函数:…...
实验室纯水器实验室超纯水机(常见类型、选型建议、维护保养)
不同实验室用水级别有何差异? 实验室用水级别由ASTM或ISO 3696等质量标准定义,有助于特定应用选择适合的水质。这些标准也考虑了生产成本,如1级(Type 1)超纯水的生产成本远高于2级(Type 2)或3级(Type 3)纯水。 1级超纯水 不含离子ÿ…...
腾讯云COS与ZKmall 开源商城的存储集成方案
ZKmall 开源商城与腾讯云对象存储(COS)的集成,可通过云端资源托管、自动化数据同步、高性能存储架构实现本地存储负载降低与访问效率提升。以下是基于搜索结果的集成路径与核心优化点: 一、存储架构升级:本地与云端协同…...
Python 深度学习实战 第3章 Keras和TensorFlowKeras 训练和评估模型实例
Python 深度学习实战 第3章 Keras和TensorFlow&Keras 训练和评估模型实例 内容概要 第3章介绍了Keras和TensorFlow的基本概念及其关系,并指导如何设置深度学习工作区。本章还概述了核心深度学习概念如何转化为Keras和TensorFlow API。通过本章,读者…...
基于SpringBoot的动物救助中心系统(源码+数据库)
500基于SpringBoot的动物救助中心系统,本系统共分为2个角色:系统管理员、用户,主要功能如下 【管理员】: 1. 登录:管理员可以通过登录系统来管理各种功能。 2. 用户管理:管理员可以查看用户列表࿰…...
【多模态大模型】《Qwen2.5-Omni》 论文解读
《Qwen2.5-Omni:重新定义端到端全模态大模型的技术范式》 论文解读 论文: https://arxiv.org/abs/2503.20215 (2025.03.26)代码: https://github.com/QwenLM/Qwen2.5-OmniNews: https://mp.weixin.qq.com/…...
go 通过汇编分析函数传参与返回值机制
文章目录 概要一、前置知识二、汇编分析2.1、示例2.2、汇编2.2.1、 寄存器传值的汇编2.2.2、 栈内存传值的汇编 三、拓展3.1 了解go中的Duff’s Device3.2 go tool compile3.2 call 0x46dc70 & call 0x46dfda 概要 在上一篇文章中,我们研究了go函数调用时的栈布…...
蓝桥杯C/C++省赛/国赛注意事项及运行环境配置
大佬的蓝桥杯考前急救指南 对拍(手动生成测试数据)代码: #include <bits/stdc.h> // 包含所有标准库的头文件 using namespace std; // 使用标准命名空间int main() {srand(time(0)); // 设置随机数种子为当前时间,确保每次…...
CSS高度坍塌?如何解决?
一、什么是高度坍塌? 高度坍塌(Collapsing Margins)是指当父元素没有设置边框(border)、内边距(padding)、内容(content)或清除浮动时,其子元素的 margin 会…...
redis的基本使用
简介 redis,Remote Dictionary Server,远程字典服务,一个基于内存的、存储键值对的数据库。redis是开源的,使用C语言编写。因为redis的数据是存储在内存中的,所以redis通常被用来做数据库的缓存 优点: re…...
【蓝桥杯】单片机设计与开发,第十二届
/*头文件声明区*/ #include <STC15F2K60S2.H>//单片机寄存器头文件 #include <init.h>//初始化底层驱动头文件 #include <led.h>//led,蜂鸣器,继电器底层驱动头文件 #include <key.h>//按键底层驱动头文件 #include <seg.h>//数码管底层驱动头…...
主流时序数据库深度对比:TDengine、InfluxDB与IoTDB的技术特性、性能及选型考量
目录 引言 一、 核心架构与技术特性对比 1.1、 TDengine:面向物联网的特定优化 1.2. InfluxDB:成熟的通用时序平台 1.3. Apache IoTDB:面向工业场景的精细化设计 二、 核心性能指标对比分析 2.1、写入性能 2.2、查询性能 三、 关键技…...
使用人工智能大模型腾讯元宝,如何免费快速做高质量的新闻稿?
今天我们学习使用人工智能大模型腾讯元宝,如何免费快速做高质量的新闻稿? 手把手学习视频地址:https://edu.csdn.net/learn/40402/666431 第一步在腾讯元宝对话框中输入如何协助老师做新闻稿,通过提问,我们了解了老师…...
国产Linux系统统信安装redis教程步骤
系统环境 uname -a Linux FlencherHU-PC 6.12.9-amd64-desktop-rolling #23.01.01.18 SMP PREEMPT_DYNAMIC Fri Jan 10 18:29:31 CST 2025 x86_64 GNU/Linux官网下载源码包并解压 下载链接 https://download.redis.io/releases/redis-7.0.15.tar.gz?_gl11h424d3_gcl_au*ODQ5…...
leetcode590 N叉树的后序遍历
前序遍历 的顺序是:根 → 子节点1 → 子节点2 → ... → 子节点N 后序遍历 的顺序是:子节点1 → 子节点2 → ... → 子节点N → 根 首先一个办法就是前序遍历结果进行翻转 在 迭代法 实现 后序遍历 时,如果采用 前序遍历 反转 的方式&…...
docker desktop 的安装和使用
一、Docker Desktop 是什么? Docker Desktop 是一款专为开发者设计的工具,可以在本地计算机(Windows/macOS)上快速运行和管理容器(Container)环境。以下是核心功能: 核心特点说明容器化开发基于…...
QCustomPlot频谱图
使用QCutomPlot做的读取txt文件显示频谱图的demo,帮助大家了解QCustomPlot的基本使用 1.运行结果 demo比较简单,用于文件读取,鼠标放大缩小,右键截图等基础功能. 2.绘图详解 绘图核心是将类提升为QCustomPlot之后进行重绘,重绘之前设计图表曲线,图标标题,坐标轴,坐标轴范围,背…...
Python 和 JavaScript两种语言的相似部分-由DeepSeek产生
Python 和 JavaScript 作为两种流行的编程语言,虽然在设计目标和应用场景上有差异(Python 偏向后端和脚本,JavaScript 偏向前端和动态交互),但它们的语法存在许多相似之处。以下是两者在语法上的主要共同点及对比&…...
记一次 .NET某云HIS系统 CPU爆高分析
一:背景 1. 讲故事 年前有位朋友找到我,说他们的系统会偶发性的CPU爆高,有时候是爆高几十秒,有时候高达一分多钟,自己有一点分析基础,但还是没找到原因,让我帮忙看下怎么回事? 二&…...
ESP32开发入门:基于VSCode+PlatformIO环境搭建指南
前言 ESP32作为一款功能强大的物联网开发芯片,结合PlatformIO这一现代化嵌入式开发平台,可以大幅提升开发效率。本文将详细介绍如何在VSCode中搭建ESP32开发环境,并分享实用开发技巧。 一、环境安装(Windows/macOS/Linux…...
在 macOS 上设置来电自启动
在 macOS 中,系统本身并不支持直接通过“接上电源适配器”自动开机(此功能涉及硬件底层控制)。但针对 Intel 处理器的 Mac 机型,可以通过以下方法间接实现类似效果。对于 Apple Silicon(M1/M2/M3)芯片的 Ma…...
【技术】Ruby 生态概念速查表,通过对比nodejs生态(入门)
以下是 Ruby 生态 对应概念的速查表,并使用与 Node.js 生态 对比的方式来参照,涵盖名称、作用(或解释)、简单用法、可能的替代方案,以及 Node.js 中最相似或可类比的工具(如果有的话)。有些工具…...
入门级宏基因组数据分析教程,从实验到分析与应用
宏基因组学彻底改变了研究人员对微生物群落的认识,微生物组不仅是环境组分,更作为共生体深刻影响着宿主的健康与功能。 鉴于微生物群落固有的复杂性及其所处环境的多样性,研究者进行一些宏基因组学研究时必须精心设计以获取能真实反映目标群体…...
解决 Vue 中 input 输入框被赋值后,无法再修改和编辑的问题
目录 需求: 出现 BUG: Bug 代码复现 解决问题: 解决方法1: 解决方法2 关于 $set() 的补充: 需求: 前段时间,接到了一个需求:在选择框中选中某个下拉菜单时,对应的…...
聚划算!CNN-GRU、CNN、GRU三模型多变量回归预测
聚划算!CNN-GRU、CNN、GRU三模型多变量回归预测 目录 聚划算!CNN-GRU、CNN、GRU三模型多变量回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 聚划算!CNN-GRU、CNN、GRU三模型多变量回归预测 (Matlab2023b 多输入单输出) 1.程…...
list的常见接口使用
今天,我们来讲解一下C关于STL标准库中的一个容器list的常见接口。 在我们之前c语言数据结构中,我们已经了解过了关于链表的知识点了,那么对于现在理解它也是相对来说比较容易的了。 数据结构--双向循环链表-CSDN博客 1. 定义与包含头文件 …...
5. 蓝桥公园
题目描述 小明喜欢观景,于是今天他来到了蓝桥公园。 已知公园有 N 个景点,景点和景点之间一共有 M 条道路。小明有 Q 个观景计划,每个计划包含一个起点 stst 和一个终点 eded,表示他想从 stst 去到 eded。但是小明的体力有限&am…...
零基础开始学习鸿蒙开发-智能家居APP离线版介绍
目录 1.我的小屋 2.查找设备 3.个人主页 前言 好久不发博文了,最近都忙于面试,忙于找工作,这段时间终于找到工作了。我对鸿蒙开发的激情依然没有减退,前几天做了一个鸿蒙的APP,现在给大家分享一下! 具体…...
你的 Linux 服务器连不上网?10 分钟入门网络故障排查
问题现象:服务器突然失去网络连接 当你兴冲冲地打开终端,准备开始一天的开发工作时,却发现服务器无法连接网络,ifconfig命令只能看到本地环回接口(lo)。这种突如其来的网络中断可能会让很多Linux新手感到手足无措。 别担心&…...
《Vue Router实战教程》20.路由懒加载
欢迎观看《Vue Router 实战(第4版)》视频课程 路由懒加载 当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件&am…...
JVM 之 String 引用机制解析:常量池、堆内存与 intern 方法
案例一: String s1 new String("1"); String s2 "1"; System.out.println(s1 s2);s1: 执行 new String("1"),JVM 首先在字符串常量池中查找或添加字面量 "1",然后在堆内存中新建一个内容为 &quo…...
如何在 Mac 上安装 Python
所有最新的 MacOS(从 macOS 12.3 开始)都预装了 Python 版本(通常是 Python 2.x),但它已经过时并且不再受支持。要充分利用 Python 的功能,您需要安装最新版本的 Python。 本文提供了分步教程,展…...
无锡东亭无人机培训机构电话
无锡东亭无人机培训机构电话,随着科技的迅猛发展,无人机逐渐走入我们的生活和工作领域,成为多种行业中不可或缺的工具。而在其广泛的应用中,如何正确、熟练地操控无人机成为了关键。因此,找到一家专业的无人机培训机构…...
WPS复制粘贴错误 ,文件未找到 mathpage.wll
文章目录 1.错误提示图片2.解决方案1.找到MathType.wll文件和MathType Commands 2016.dotm文件并复制2.找到wps安装地址并拷贝上述两个文件到指定目录 3.重启WPS 1.错误提示图片 2.解决方案 1.找到MathType.wll文件和MathType Commands 2016.dotm文件并复制 MathType.wll地址如…...
蓝桥杯单片机刷题——按键设置当前采集距离为距离参数
设计要求 驱动超声波传感器,启动距离测量功能,并将其结果显示到数码管上。 按键“S5”定义为参数按键,按下S5按键,设备自动将当前采集的距离数据作为距离参数; 若测量的距离数据超过距离参数,指示灯L1点亮ÿ…...
mybaties plus 更新null值进入数据库
(数据库一定要支持字段为null值) 问题: 假设我现在数据库里有一个值是1,这个字段允许为null。 目前我使用的是的mybaties plus,我希望将这个值更新weinull,如何操作? 提示:如果直接…...
VSCode优雅的使用debug
原始用法:(这里不使用) 配置launch.json,里面传入参数然后debug,这里我们通常需要传入的参数比较多,而且经常修改参数,直接去修改launch.json会比较麻烦,所以使用sh脚本比较方便。 {// Use IntelliSense to…...
优化你的 REST Assured 测试:设置默认主机与端口、GET 请求与断言
REST Assured 是一个功能强大的 Java 库,用于测试 RESTful Web 服务。它简化了 API 测试流程,提供了一整套用于高效验证响应的工具。在本篇博客中,我们将深入探讨几个核心概念,包括如何设置默认主机和端口、如何发起 GET 请求以及…...
JVM之String创建、拼接
一、字符串创建的两种方式 1. 字面量直接赋值 String s1 "a"; 过程: JVM 检查字符串常量池中是否存在 "a"。若存在,直接返回常量池中的引用。若不存在,在常量池中创建 "a",返回其引用。 特点&a…...
UE5 模仿生存建造类游戏创建的过程
一、大概流程如下 点击界面按钮生成Actor->移动鼠标Actor的位置随着鼠标移动移动->点击鼠标左键确定Actor的位置 使用了盒体检测GetWorld()->SweepSingleByChannel()函数检测是否发生碰撞通过 FCollisionQueryParams CollisionParams;CollisionParams.AddIgnoredAc…...
大模型在慢性髓细胞白血病(CML)初治成人患者诊疗中的应用研究
目录 一、引言 1.1 研究背景与意义 1.2 国内外研究现状 1.3 研究目的与内容 二、大模型技术与 CML 相关知识 2.1 大模型技术原理与特点 2.2 CML 的病理生理与诊疗现状 三、术前风险预测与手术方案制定 3.1 术前数据收集与预处理 3.2 大模型预测术前风险 3.3 根据预测…...
汽车性能的幕后保障:慧通测控电动尾翼综合力学测试浅析
在汽车性能不断追求极致的当下,电动尾翼已成为众多高性能车型以及部分新能源汽车提升空气动力学表现与操控稳定性的关键配置。从炫酷的超跑到注重续航与驾驶体验的新能源车,电动尾翼正逐渐崭露头角。它绝非仅仅是外观上的装饰,而是能在车辆行…...
动力电池自动点焊机:新能源汽车制造的智能焊接利器
在新能源汽车产业蓬勃发展的今天,动力电池作为其核心部件,其性能与安全性直接关系到整车的续航里程和使用寿命。而动力电池的制造过程中,焊接工艺是至关重要的一环。这时,动力电池自动点焊机便以其高效、精准、智能的特点…...
arm64架构的copy_from_user分析
文章目录 前言代码实现内核c代码copy_from_user_copy_from_userraw_copy_from_user 内核汇编代码copy_from_user.Scopy_template.S 汇编代码分析汇编简介标签.req伪指令.macro伪指令tbz指令neg指令str指令 copy_template.S分析 小结 前言 一谈到内核-用户空间的数据拷贝&#…...
【远程工具】1.1 时间处理设计与实现(datetime库lib.rs)
一、设计原理与决策 时间单位选择 采用**秒(s)**作为基准单位,基于以下考虑: 国际单位制(SI)基本时间单位 整数秒(i64)方案优势: 精确无误差(相比浮点数&am…...