go 基础语法 【教程 go tour】
go 基础语法 【1】
教程go tour
1 包 变量 函数
- 变量不用声明
func swap(x, y string) (string, string) {return y, x
}func main() {a, b := swap("hello", "world")fmt.Println(a, b)
}
-
也可以声明:
-
没有明确初始化的变量声明会被赋予对应类型的 零值。
零值是:
- 数值类型为
0
, - 布尔类型为
false
, - 字符串为
""
(空字符串)。
- 数值类型为
func main() {var i intvar f float64var b boolvar s stringfmt.Printf("%v %v %v %q\n", i, f, b, s)
}
//输出
0 0 false ""
-
变量声明可以包含初始值,每个变量对应一个。
如果提供了初始值,则类型可以省略;变量会从初始值中推断出类型。
var i, j int = 1, 2func main() {var c, python, java = true, false, "no!"fmt.Println(i, j, c, python, java)
}
-
在函数中,短赋值语句
:=
可在隐式确定类型的var
声明中使用。函数外的每个语句都 必须 以关键字开始(
var
、func
等),因此:=
结构不能在函数外使用。
var i, j = 1, 2k := 3c, python, java := true, false, "no!"
//等价于 var c, python, java = true, false, "no!"
- go基本类型
boolstringint int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptrbyte // uint8 的别名rune // int32 的别名// 表示一个 Unicode 码位float32 float64complex64 complex128
var (ToBe bool = falseMaxInt uint64 = 1<<64 - 1z complex128 = cmplx.Sqrt(-5 + 12i)
)func main() {fmt.Printf("类型:%T 值:%v\n", ToBe, ToBe)fmt.Printf("类型:%T 值:%v\n", MaxInt, MaxInt)fmt.Printf("类型:%T 值:%v\n", z, z)
}
-
常量
- 常量的声明与变量类似,只不过使用
const
关键字。 - 常量可以是字符、字符串、布尔值或数值。
- 常量不能用
:=
语法声明。
const World = "世界" const Truth = true const Pi = 3.14
- 常量的声明与变量类似,只不过使用
-
数值常量
数值常量是高精度的 值。
一个未指定类型的常量由上下文来决定其类型。
const (// 将 1 左移 100 位来创建一个非常大的数字// 即这个数的二进制是 1 后面跟着 100 个 0Big = 1 << 100// 再往右移 99 位,即 Small = 1 << 1,或者说 Small = 2Small = Big >> 99 )
2流程控制
for
- 初始化语句和后置语句是可选的。
- 可以去掉分号,因为 C 的
while
在 Go 中叫做for
。
for i := 0; i < 10; i++ {sum += i}
for ; sum < 1000; {sum += sum
}
for sum < 1000 {sum += sum
}
//无限循环
for {}
if
-
if
语句可以在条件表达式前执行一个简短语句。该语句声明的变量作用域仅在
if
之内。
func pow(x, n, lim float64) float64 {if v := math.Pow(x, n); v < lim {return v}return lim
}
- (在
main
的fmt.Println
调用开始前,两次对pow
的调用均已执行并返回其各自的结果。)
func pow(x, n, lim float64) float64 {if v := math.Pow(x, n); v < lim {return v} else {fmt.Printf("%g >= %g\n", v, lim)}// can't use v here, thoughreturn lim
}func main() {fmt.Println(pow(3, 2, 10),pow(3, 3, 20),)
}//输出:注意输出顺序
27 >= 20
9 20
*循环与函数练习:
题目
实现一个平方根函数:给定一个数 x,我们需要找到一个数 z 使得 z² 尽可能地接近 x。
计算机通常使用循环来计算 x 的平方根。从某个猜测的值 z 开始,我们可以根据 z² 与 x 的近似度来改进 z,产生一个更好的猜测:
z -= (z*z - x) / (2*z)
重复调整的过程,猜测的结果会越来越精确,得到的答案也会尽可能接近实际的平方根。
请在提供的
func Sqrt
中实现它。无论输入是什么,可以先猜测 z 为 1。 首先,重复计算 10 次并连续打印每次的 z 值。观察对于不同的 x 值(1、2、3 …), 你得到的答案是如何逼近结果的,以及猜测改进的速度有多快。
实现
package mainimport ("fmt""math"
)func Sqrt(x float64) float64 {z := 1.0 // 修正了变量声明t := math.Abs(z*z - x)for i := 0; i < 10; i++ {if z*z > x { // 修正了条件语句的语法z -= (z*z - x) / (2 * z)} else {z += (z*z - x) / (2 * z)}fmt.Printf("当前是第%d次,z:%f,z*z:%f,x:%f\n", i, z,z*z, x) // 修正了格式化字符串t = math.Abs(z*z - x)fmt.Printf("当前t值为:%f\n",t)if t==0.0 {break}}return z
}func main() {fmt.Println(Sqrt(102))
}
- 当x很小时,基本7、8次就可以得到结果
switch 分支
- Go 只会运行选定的
case
,而非之后所有的case
。 在效果上,Go 的做法相当于这些语言中为每个case
后面自动添加了所需的break
语句。 - 在 Go 中,除非以
fallthrough
语句结束,否则分支会自动终止。 - Go 的另一点重要的不同在于
switch
的case
无需为常量,且取值不限于整数。
func main() {t := time.Now()switch {case t.Hour() < 12:fmt.Println("早上好!")case t.Hour() < 17:fmt.Println("下午好!")default:fmt.Println("晚上好!")}
}
switch
的case
语句从上到下顺次执行,直到匹配成功时停止。
defer 推迟
defer 语句会将函数推迟到外层函数返回之后执行。
推迟调用的函数其参数会立即求值,但直到外层函数返回前该函数都不会被调用
- 推迟调用的函数调用**会被压入一个栈中**。 当外层函数返回时,被推迟的调用会按照后进先出的顺序调用。
func main() {defer fmt.Println("world1")fmt.Println("hello")defer fmt.Println("world2")defer fmt.Println("world3")fmt.Println("hello2")
}//输出
hello
hello2
world3
world2
world1
3.结构体 切片 映射
指针
Go 拥有指针。指针保存了值的内存地址。
- 类型
*T
是指向T
类型值的指针,其零值为nil
。
var p *int
&
操作符会生成一个指向其操作数的指针。
i := 42
p = &i
*
操作符表示指针指向的底层值。
fmt.Println(*p) // 通过指针 p 读取 i
*p = 21 // 通过指针 p 设置 i
这也就是通常所说的「解引用」或「间接引用」。
- 与 C 不同,Go 没有指针运算。
func main() {i, j := 42, 2701p := &i // 指向 ifmt.Println(*p) // 通过指针读取 i 的值*p = 21 // 通过指针设置 i 的值fmt.Println(i) // 查看 i 的值p = &j // 指向 j*p = *p / 37 // 通过指针对 j 进行除法运算fmt.Println(j) // 查看 j 的值
}
42
21
73
结构体
- 一个 结构体(
struct
)就是一组 字段(field)。
type Vertex struct {X, Y int
}var (v1 = Vertex{1, 2} // 创建一个 Vertex 类型的结构体v2 = Vertex{X: 1} // Y:0 被隐式地赋予零值v3 = Vertex{} // X:0 Y:0p = &Vertex{1, 2} // 创建一个 *Vertex 类型的结构体(指针)
)func main() {fmt.Println(Vertex{1, 2})v := Vertex{3, 5}p2 := &vp2.X = 1e9 //等价于(*p2).X fmt.Println(v)fmt.Println(v1, p, v2, v3)
}
//输出
{1 2}
{1000000000 5}
{1 2} &{1 2} {1 0} {0 0}
数组
-
类型
[n]T
表示一个数组,它拥有n
个类型为T
的值。 -
表达式
var a [10]int
-
数组的长度是其类型的一部分,因此数组不能改变大小。
var a [2]string
a[0] = "Hello ww"
a[1] = "World"
fmt.Println(a[0], a[1])
fmt.Println(a)primes := [6]int{2, 3, 5, 7, 11, 13}
//var primes = [6]int{2, 3, 5, 7, 11, 13}
切片
-
类型
[]T
表示一个元素类型为T
的切片。. -
切片通过两个下标来界定,一个下界和一个上界,二者以冒号分隔:
a[low : high]
-
它会选出一个半闭半开区间,包括第一个元素,但排除最后一个元素。
-
长度为high-low
-
更改切片的元素会修改其底层数组中对应的元素。和它共享底层数组的切片都会观测到这些修改。
func main() {names := [4]string{"John","Paul","George","Ringo",}fmt.Println(names)a := names[0:2]b := names[1:3]fmt.Println(a, b)b[0] = "XXX"fmt.Println(a, b)fmt.Println(names)
}[John Paul George Ringo]
[John Paul] [Paul George]
[John XXX] [XXX George]
[John XXX George Ringo]
- 切片字面量
[3]bool{true, true, false}
//等价于
[]bool{true, true, false}s := []struct {i intb bool}{{2, true},{3, false},{5, true},{7, true},{11, false},{13, true},}
- 默认行为:切片下界的默认值为 0,上界则是该切片的长度。
//等价表达式
a[0:10]
a[:10]
a[0:]
a[:]
func main() {s := []int{2, 3, 5, 7, 11, 13}s = s[1:4]fmt.Println(s)s = s[:2] //0:2fmt.Println(s)s = s[1:]//1:2fmt.Println(s)
}
[3 5 7]
[3 5]
[5]
- 切片的容量不会改变,长度会改变
- 切片的长度就是它所包含的元素个数。
len(s)
- 切片的容量是从它的第一个元素开始数,到其底层数组元素末尾的个数。
cap(s)
func main() {s := []int{2, 3, 5, 7, 11, 13}printSlice(s)// 截取切片使其长度为 0s = s[:0]printSlice(s)// 扩展其长度s = s[:4]printSlice(s)// 舍弃前两个值s = s[2:]printSlice(s)
}func printSlice(s []int) {fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}//输出
len=6 cap=6 [2 3 5 7 11 13]
len=0 cap=6 []
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]
-
使用切片会比直接使用数组更方便
-
切片的零值是
nil
。nil 切片的长度和容量为 0 且没有底层数组。
func main() {var s []intfmt.Println(s, len(s), cap(s))if s == nil {fmt.Println("nil!")}
}
[] 0 0
nil!
- make:用内置函数
make
来创建切片
a := make([]int, 5) // len(a)=5
//指定容量
b := make([]int, 0, 5) // len(b)=0, cap(b)=5b = b[:cap(b)] // len(b)=5, cap(b)=5
b = b[1:] // len(b)=4, cap(b)=4
- 举例,注意容量是和底层的数组容量相关
func main() {a := make([]int, 5)printSlice("a", a)b := make([]int, 0, 5)printSlice("b", b)c := b[:2]d := c[2:5]c[1]=1 printSlice("c", c)printSlice("d", d)
}func printSlice(s string, x []int) {fmt.Printf("%s len=%d cap=%d %v\n",s, len(x), cap(x), x)
}
//结果
a len=5 cap=5 [0 0 0 0 0]
b len=0 cap=5 []
//c 的 cap 是 5,因为它的起始下标是底层数组的 0,容量就是 5-0=5。
//d 的 cap 是 3,因为它的起始下标是底层数组的 2,容量就是 5-2=3。
c len=2 cap=5 [0 1]
d len=3 cap=3 [0 0 0]
- 追加元素
append
func main() {var s []intprintSlice(s)// 可在空切片上追加s = append(s, 0)printSlice(s)// 这个切片会按需增长s = append(s, 1)printSlice(s)// 可以一次性添加多个元素s = append(s, 2, 3, 4)printSlice(s)
}
len=0 cap=0 []
len=1 cap=1 [0]
len=2 cap=2 [0 1]
len=5 cap=6 [0 1 2 3 4]
- range遍历
使用 for
循环遍历切片时,每次迭代都会返回两个值。
- 第一个值为当前元素的下标
- 第二个值为该下标所对应元素的一份副本。
var pow = []int{1, 2, 4, 8, 16, 32}func main() {for i, v := range pow {fmt.Printf("2**%d = %d\n", i, v)}
}
2**0 = 1
2**1 = 2
2**2 = 4
2**3 = 8
2**4 = 16
2**5 = 32//忽略
for i, _ := range pow
for _, value := range pow
//只需索引
for i := range pow
*切片练习
题目:
实现 Pic
。它应当返回一个长度为 dy
的切片,其中每个元素是一个长度为 dx
,元素类型为 uint8
的切片。当你运行此程序时,它会将每个整数解释为灰度值 (好吧,其实是蓝度值)并显示它所对应的图像。
图像的解析式由你来定。几个有趣的函数包括 (x+y)/2
、x*y
、x^y
、x*log(y)
和 x%(y+1)
。
(提示:需要使用循环来分配 [][]uint8
中的每个 []uint8
。)
(请使用 uint8(intValue)
在类型之间转换;你可能会用到 math
包中的函数。)
实现
package mainimport ("golang.org/x/tour/pic""math"
)func Pic(dx, dy int) [][]uint8 {matrix := make([][]uint8,dy)//循环分配for row := range matrix {matrix[row] = make([]uint8, dx) // 为每一行分配列for i:=range matrix[row]{//1 matrix[row][i]=(uint8(i)+uint8(row))/2//2 matrix[row][i]=(uint8(i+1)*uint8(row+1))//3 matrix[row][i]=(uint8(i)^uint8(row))//4 matrix[row][i]=(uint8(i)*uint8(math.Log(float64(row+1))))}}return matrix}
func main() {pic.Show(Pic)
}
map
- 映射,key-value
- 映射的零值为
nil
。nil
映射既没有键,也不能添加键。 make
函数会返回给定类型的映射,并将其初始化备用。
//m = make(map[ key ] value)
type Vertex struct {Lat, Long float64
}
var m map[string]Vertexfunc main() {m = make(map[string]Vertex)m["Bell Labs"] = Vertex{40.68433, -74.39967,}m["11 Labs"] = Vertex{41.68433, -73.39967,}fmt.Println(m["Bell Labs"])fmt.Println(m["11 Labs"])fmt.Println(len(m))
}//输出
{40.68433 -74.39967}
{41.68433 -73.39967}
2
映射字面量(Map literals)
- 必须有键名
var m = map[string]Vertex{"Bell Labs": Vertex{40.68433, -74.39967,},"Google": Vertex{37.42202, -122.08408,},
}
修改映射
在映射 m
中插入或修改元素:
m[key] = elem
获取元素:
elem = m[key]
删除元素:
delete(m, key)
通过双赋值检测某个键是否存在:
- 若
key
在m
中,ok
为true
;否则,ok
为false
。 - 若
key
不在映射中,则elem
是该映射元素类型的零值。
短变量声明:
elem, ok = m[key]
*练习:映射
实现 WordCount
。它应当返回一个映射,其中包含字符串 s
中每个“单词”的个数。 函数 wc.Test
会为此函数执行一系列测试用例,并输出成功还是失败。
实现:
package mainimport ("golang.org/x/tour/wc""strings"
)func WordCount(s string) map[string]int {//strings.Fields 会根据空白字符分割字符串并返回一个字符串切片str :=strings.Fields(s)//定义一个映射(map)时,必须使用 make 函数或直接初始化//var m = make(map[string]int)等价于下面的两行var m map[string]intm=make(map[string]int)for _,word:=range str{m[word]+=1} return m
}func main() {wc.Test(WordCount)
}
- 注意使用strings.Fields方法
- 注意map需要初始化
函数值
- 函数可以像值一样传递
- 函数值可以用作函数的参数或返回值。
func compute(fn func(float64, float64) float64) float64 {return fn(3, 4)
}func main() {hypot := func(x, y float64) float64 {return math.Sqrt(x*x + y*y)}fmt.Println(hypot(5, 12))fmt.Println(compute(hypot))fmt.Println(compute(math.Pow))
}
解释:
-
compute
函数:func compute(fn func(float64, float64) float64) float64 {return fn(3, 4) }
compute
接受一个函数fn
,该函数参数是两个float64
类型,并返回一个float64
。- 在
compute
中,调用fn(3, 4)
,并返回结果。
-
main
函数:func main() {hypot := func(x, y float64) float64 {return math.Sqrt(x*x + y*y)}fmt.Println(hypot(5, 12)) // 计算 5 和 12 的斜边长度fmt.Println(compute(hypot)) // 调用 compute,传入 hypotfmt.Println(compute(math.Pow)) // 调用 compute,传入 math.Pow }
hypot
是一个匿名函数,用于计算给定两个直角边x
和y
的斜边长度(使用勾股定理)。fmt.Println(hypot(5, 12))
计算并打印斜边长度,即13
。
-
compute(hypot)
:- 调用
compute
,传入hypot
函数,返回hypot(3, 4)
的结果,即5
。
- 调用
-
compute(math.Pow)
:math.Pow
是一个标准库函数,计算x
的y
次方。compute(math.Pow)
将调用math.Pow(3, 4)
,结果是81
。
函数闭包
闭包是一个函数值,它引用了其函数体之外的变量。 该函数可以访问并赋予其引用的变量值,换句话说,该函数被“绑定”到了这些变量。
package mainimport "fmt"func adder() func(int) int {sum := 0return func(x int) int {sum += xreturn sum}
}func main() {pos, neg := adder(), adder()for i := 0; i < 10; i++ {fmt.Println(pos(i),neg(-2*i),)}
}
0 0
1 -2
3 -6
6 -12
10 -20
15 -30
21 -42
28 -56
36 -72
45 -90
这段 Go 代码展示了闭包的概念。闭包是一个函数,它捕获了其外部作用域的变量。下面逐步解释代码的每个部分。
解释
-
adder
函数:func adder() func(int) int {sum := 0return func(x int) int {sum += xreturn sum} }
adder
函数返回一个匿名函数(闭包)。- 在
adder
内部,定义了一个变量sum
,初始值为0
。 - 返回的匿名函数接受一个
int
类型参数x
,每次调用时将x
加到sum
上,并返回新的sum
值。
-
main
函数:func main() {pos, neg := adder(), adder()for i := 0; i < 10; i++ {fmt.Println(pos(i),neg(-2*i),)} }
- 调用
adder
两次,分别创建两个闭包pos
和neg
。 pos
用于计算正数的累加和,neg
用于计算负数的累加和。- 在循环中,从
0
到9
迭代,调用pos(i)
和neg(-2*i)
。
- 调用
输出解释
pos(i)
将i
依次加到sum
中,输出0
到9
的累加和。neg(-2*i)
将-2*i
依次加到sum
中,输出0
到-18
的累加和。
闭包的特性
- 状态保持:每个闭包都有自己的
sum
变量,互不影响。pos
和neg
各自维护自己的状态。 - 函数作为第一类公民:在 Go 中,函数可以作为返回值,允许创建灵活的和可重用的代码。
允许每个 adder
实例独立维护其状态,通过返回的函数可以对状态进行修改和访问。
*练习:斐波纳契闭包
题目:
实现一个 fibonacci
函数,它返回一个函数(闭包),该闭包返回一个斐波纳契数列 (0, 1, 1, 2, 3, 5, …)。
实现:
package mainimport "fmt"// fibonacci 是返回一个「返回一个 int 的函数」的函数
func fibonacci() func() int {var a,b,c=1,0,0return func() int {c=a+ba=bb=creturn a}
}func main() {f := fibonacci()for i := 0; i < 10; i++ {fmt.Println(f())}
}
相关文章:
go 基础语法 【教程 go tour】
go 基础语法 【1】 教程go tour 1 包 变量 函数 变量不用声明 func swap(x, y string) (string, string) {return y, x }func main() {a, b : swap("hello", "world")fmt.Println(a, b) }也可以声明: 没有明确初始化的变量声明会被赋予对应…...

养生指南:五维打造健康新方式
一、饮食:天然搭配,科学进食 遵循 “食物多样化” 原则,早餐以红薯玉米粥搭配水煮蛋、凉拌黄瓜,开启活力一天;午餐选用糙米饭、番茄炖牛腩、蒜蓉空心菜,营养均衡;晚餐用冬瓜虾皮汤配上蒸芋头&a…...

网络爬虫学习之httpx的使用
开篇 本文整理自《Python3 网络爬虫实战》,主要是httpx的使用。 笔记整理 使用urllib库requests库的使用,已经可以爬取绝大多数网站的数据,但对于某些网站依然无能为力。 这是因为这些网站强制使用HTTP/2.0协议访问,这时urllib和r…...

无人机桥梁检测效率问题-高精度3D建模及航线规划
无人机桥梁检测效率问题-高精度3D建模及航线规划 无人机桥梁检测的效率分析 结论-并没有提升效率 飞行任务制定步骤繁琐且续航限制 需要首先对大桥建立高精度的3D建模,根据任务制定无人机的飞行路径以及动作,商用无人机续航通常仅30-40分钟,…...

想免费使用 AWS 云服务器?注册、验证及开通全攻略
拥有一台 AWS 免费云服务器,可以轻松搭建个人网站、博客或部署 ChatGPT 等 AI 服务。本文详解如何 注册 AWS 账号、完成 信用卡验证,并在 AWS 控制台中 开通 EC2 实例,享受长达 12 个月的免费额度。 提示: 国内信用卡及银联借记卡…...
以太联 - Intellinet 闪耀台北 SecuTech 国际安全科技应用博览会
2025 年 5 月 7 日至 9 日,台北 SecuTech 国际安全科技应用博览会现场热闹非凡,以太联 - Intellinet 携旗下前沿产品与解决方案精彩亮相,成为展会上一道亮丽的风景线,吸引了众多业内人士的目光,收获了广泛关注与高度认…...

Pandas:数据分析中的缺失值检测、加载、设置、可视化与处理
本文目录: 一、检测数据集中的缺失值(一)缺失值的判断规则:(二)代码如下: 二、缺失值加载处理&缺失值设置(一)缺失值加载处理(二)缺失值设置 …...

【Linux系列】EVS 与 VBD 的对比
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

56 在standby待机打通uart调试的方法
修改点如下: 一,进入standby保证uart通 1, 去掉串口进入休眠RT_DEVICE_CTRL_SUSPEND:关闭uart,保证BSP_IO_Power_Down函数执行完前,串口都可以打印,和通过SifliUsartServer工具串口连接,并debug死机问题&…...

OceanBase 共享存储:云原生数据库的存储
目录 探会——第三届 OceanBase 开发者大会 重磅发布:OceanBase 4.3 开发者生态全面升级 实战演讲:用户案例与行业落地 OceanBase 共享存储架构解析 什么是共享存储架构? 云原生数据库的架构 性能、弹性与多云的统一 为何OceanBase能…...

安卓新建项目时,Gradle下载慢下载如何用国内的镜像
方法 1:修改 gradle-wrapper.properties 使用国内镜像 Gradle 的下载地址可以在 gradle-wrapper.properties 中修改,替换为国内镜像地址(如阿里云、腾讯云等)。 步骤 打开项目中的 gradle-wrapper.properties 文件(路…...

讯联文库开发日志(五)登录拦截校验
零 在此之前,由于主播一直缺乏session,这次两个小时的寻找bug之旅也让我受益颇多 罪魁祸首:key值写错了,导致一直报错,不过这也让我了解了更多关于session的k-v结构 参数校验 我们需要在全局拦截器注解里面加两个方…...

PCB设计教程【入门篇】——电路分析基础-读懂原理图
前言 本教程基于B站Expert电子实验室的PCB设计教学的整理,为个人学习记录,旨在帮助PCB设计新手入门。所有内容仅作学习交流使用,无任何商业目的。若涉及侵权,请随时联系,将会立即处理 目录 前言 一、原理图核心要素…...

C语言数据结构
单链表 头文件:lin.h #ifndef __LINK_H__ #define __LINK_H__ #include <stdio.h> #include <stdlib.h> typedef int DataType; /*节点数据类型*/ typedef struct node { DataType data; //数据域 struct node *pNext; …...
湖北理元理律师事务所债务优化方案:让还款与生活平衡成为可能
在现代社会,债务问题已经成为影响许多家庭生活质量的重要因素。如何在不影响基本生活的前提下合理规划还款,是众多债务人面临的实际难题。湖北理元理律师事务所推出的债务优化服务,正是针对这一需求而设计的专业解决方案。 该所的债务优化方…...
Java对象内存分配优化教学
用 “停车位” 的比喻理解这个问题 🚗💨 假设你是一个停车场管理员(JVM),现在有人(程序员)要停车(new 对象)。传统认知是: 堆内存 公共停车场 栈内存 临时…...

精度再升级,可到微米!单位自动换算平米和米
CAD图纸单位怎么看?精度怎么调? 长度测出来是什么单位? 面积一大串怎么回事? 坐标小数点位置不对怎么办? 点击直接获取CAD快速看图 首先说原理 CAD图纸在绘制时,一般情况下单位是: 长度---…...
【学习笔记】Sophus (Python) 使用文档
以下是一份针对 Sophus 库的 Python 使用文档,涵盖基础概念、安装方法、核心功能及代码示例。内容围绕 SO3(3D旋转群)和 SE3(3D刚体变换群)展开,适合机器人学、SLAM、三维几何等领域。 Sophus (Python) 使用…...

常见算法题目2 - 给定一个字符串,找出其中最长的不重复子串
算法题目2 - 给定一个字符串,找出其中最长的不重复子串 1. 问题描述 给定一个字符串,输出其最长的不重复子串,例如: String str "ababc"; 输出: abc以下根据两种搜索算法。 2. 算法解决 2.1 暴力循环法…...

如何配置jmeter做分布式压测
问:为何需要做分布式 答:当我们本地机器jmeter进行压测时,单台JMeter机器通常无法稳定生成2000 QPS(受限于CPU、内存、网络带宽),本地端口耗尽:操作系统可用的临时端口(Ephemeral P…...

Django 中的 ORM 基础语法
深入剖析 Django 中的 ORM 语法:从基础到实战进阶 在 Django 开发领域,ORM(对象关系映射)是开发者高效操作数据库的得力工具。它以简洁直观的 Python 代码,替代繁琐的 SQL 语句,极大提升了开发效率。本文将…...
C#对象初始化语句:优雅创建对象的黑科技
📌 核心概念速览 对象初始化语句(Object Initializer)是C#中一种简洁高效的语法糖,允许在创建对象时直接初始化其公有字段或属性,无需依赖构造函数的重载。它的本质是对构造过程的扩展,尤其适合需要灵活设…...

【计算机网络】TCP如何保障传输可靠性_笔记
文章目录 一、传输可靠性的6方面保障二、分段机制三、超时重传机制四、流量控制五、拥塞控制 提示:以下是本篇文章正文内容,下面案例可供参考 源网站 按TCP/IP 4层体系,TCP位于传输层,为应用层提供服务 一、传输可靠性的6方面保障…...
Robust Kernel Estimation with Outliers Handling for Image Deblurring论文阅读
Robust Kernel Estimation with Outliers Handling for Image Deblurring 1. 论文的研究目标与实际问题意义1.1 研究目标1.2 实际问题与产业意义2. 论文的创新方法、模型与优势2.1 核心思路2.2 关键公式与技术细节2.2.1 非线性模糊模型与能量函数2.2.2 中间潜像更新与IRLS2.2.3…...
Android Studio 开发环境兼容性检索(AGP / Gradle / Kotlin / JDK)
本表检索了 Android 项目中常用构建工具的兼容性关系,包括: AGP(Android Gradle Plugin)Gradle(构建工具)KGP(Kotlin Gradle Plugin)JDK(Java Development Kitÿ…...

html主题切换小demo
主题切换功能为网页和应用程序提供了多样化的视觉风格与使用体验。实现多主题切换的技术方案丰富多样,其中 CSS 变量和 JavaScript 样式控制是较为常见的实现方式。 以下是一个简洁的多主题切换示例,愿它能为您的编程之旅增添一份趣味。 代码展示 <…...

AI架构职责分配——支持AI模块的职责边界设计
职责分配——支持AI模块的职责边界设计 在传统系统中,职责分配通常围绕“控制层处理逻辑、服务层执行业务、数据层持久化”进行划分。这种分工逻辑在纯业务系统中足以支撑高效协作与系统演进。然而,随着AI模块的引入,系统中新增了如模型推理…...
git@gitee.com: Permission denied (publickey). fatal: 无法读取远程仓库
错误信息: gitgitee.com: Permission denied (publickey). fatal: 无法读取远程仓库。  说明 Git 无法通过 SSH 密钥成功连接到 Gitee(码云)仓库。这通常是由于 SSH 密钥未正确配置或未添加到 Gitee 账户所致。 &am…...

CARIS HIPS and SIPS 12.1是专业的多波束水深数据和声呐图像处理软件
CARIS HIPS 和 SIPS 是一套综合水文处理软件,主要用于海洋水道处理和测量领域。该软件集成了测深、水柱和海底图像处理功能,能够提高业务处理的精确度和效率。 主要功能和应用场景 测深数据处理:HIPS主要用于处理大型测深数据。 …...
Docker端口映射与容器互联
Docker端口映射与容器互联 1. 端口映射实现容器访问 1.1 从外部访问容器应用 # 基础端口映射语法 docker run -d -p [宿主机端口]:[容器端口] [镜像名称]# 示例:容器80端口→宿主机8080 docker run -d -p 8080:80 nginx1.2 高级映射配置 映射类型命令示例说明文档…...