Go语言基础
Go的数据类型定义
//运行第一个程序package main
func main(){print("Hello World")
}
在GO语言中,一个程序只能有一个main包,对应只能有一个main方法,若无法满足这个条件,编译时将会报错。注释方式与PHP相同
- import的使用
个人在使用import时,按照自己的编写习惯,依赖IDE的自动导包功能,实现包的导入。若导入包后没有使用,会编译出错。
// 使用 . 来实现省略调用
import . "fmt"// 在包前通过别名替代包名
import stdio "fmt"// 包前使用 _ 作用为只调取包的init方法
import _ "xxx"// 使用 () 实现多包导入
import ("fmt""os"
)
- GO的可见性
GO通过大小写来判别函数或者变量的权限,小写则为private,大写为public
- 定义数据结构
GO定义数据类型比较有意思。在函数体内使用var定义的变量必须被使用,否则编译报错,申明外部变量没有限制
- 布尔类型
布尔类型只有true与false两个值,不可用0与1替代
- 整形
int类型根据使用的平台自动判别32位还是64位,可以手动定义指定的位数,例如 int8/uint16,定义了指定8位的int型/16位的无符号int型
- 浮点型
浮点型有float32/float64,精确范围对应7/15位
- 复数类型
complex64/complex128
- 其他值类型
array struct string
- 引用类型
slice map chan
- 接口类型
inteface
- 函数类型
func
// 定义单个变量
var hello = "Hello World"//定义多个变量
var(num = 321str = "haha"
)//定义常量,定义多个常量与变量的定义一样
const PI =3.14
- 类型零值
零值不等于空值,变量被声明为某种类型后的默认值,通常情况下整型的默认值为0,bool为false,string为空字符串
- 类型别名的定义
利用type进行类型别名的定义
type(
chinese string
intMax int64
)
- 变量声明与赋值
变量的声明格式:var <name> <type>变量的赋值格式:<name> = <value>声明的同时赋值:var <name> [type] = <value>自身推断赋值:var <name> = <value>简写赋值(不可全局变量赋值使用) <name> := <value>
- 类型转换
进行类型转换时,需要进行显式转换,并且需要保证两个不同的类型转换可以互相兼容
var a = 'a'
b := int(a)
- 常量的定义问题
常量值在编译时已经确定,所以右侧的数据需要使用常量或者内置函数,变量不能进行常量的赋值。定义常量组时,如果不进行数值的赋值,将会将其数值赋值为其上行的数值。常量初始化规则定义了每一行的常量定义个数一致时,默认上行数值下行初始化将进行,否则报错。
常量的iota是常量计数器,只在常量的表达式中使用。const中每新增一行常量声明将使iota计数一次
// 赋值b,c均为hello字符串,赋值g,h为1,2
const(a = "hello"bce,f = 1,2g,h
)// 输出 c为2 f为5
const(a=1bc = iotadef = iota
)
运算符
1、运算符的基本介绍
运算符是一种特殊的符号,可以表示数据的运算,赋值,比较等
1)算术运算符

2)赋值运算符

3)比较运算符

4)逻辑运算符

5)位运算符

6)其他运算符

比较两个数的大小。
package leeimport "fmt"func Test(){a:=101b:=66if(a>b){fmt.Printf("a大一些")}else{fmt.Printf("b大一些")}
}
注意:go语言不支持三元运算符
2、运算符的优先级

控制语句
- if条件判断
if条件判断:在布尔表达式里面可以定义变量,并行赋值.变量的作用域只能作用在代码块里面.
// 格式:
if <布尔表达式>{语句块
}else if <布尔表达式>{语句块
}else{语句块
}// 定义i=5 输出5,下面一句会编译出错
if i:=5;i<10{print(i)
}
print(i)
- 循环控制
go可以使用for完成所有的循环操作,变量的作用域只能作用在代码块里面
//经典for循环结构
for i:=1;i<100;i++{print(i)
}//单条件(while式)for循环结构
for true{print("进入死循环")
}// 无条件式
for {print("hello")
}
- switch语句
switch不需要使用break,自动进行跳出,若需要连续条件选择,使用fallthrough。
// 常规操作
i := 3
switch i{case 1:print(1)case 2:print(2)case 3:print(3)default:print(4)
}// 在表达式中定义变量
switch i=3; {case i==1:print(1)case i==2:print(2)case i==3:print(3)default:print(4)
}// 使用fallthrough 输出2 3
i := 2
switch i{case 1:print(1)case 2:print(2)fallthroughcase 3:print(3)default:print(4)
}
复制
- 跳转语句
goto break continue 三者均可以执行跳转。
goto用于调整执行位置。使用时,注意标签的位置
break用于循环语句中跳出循环,并开始执行循环之后的语句
continue不是跳出循环,而是跳过当前循环执行下一次循环语句,一般用于for 循环中,触发for增量语句的执行。
//goto操作 这里输出 你好,这里是跳转
START:print("你好,这里是跳转")os.Exit(1)for i:=1; i<3;i++ {goto START}print("这里是测试是否跳转")// break操作 输出 跳出了循环start
START:for i:=1;i<=2 ;i++ {break START}print("跳出了循环start")//continue操作 输出 2 4 6 8
for i:=1;i<10 ;i++ {if(i%2!=0){continue}print(i)
}
数组
数组的定义格式 var < name > [n]< type >。
数组赋值时,两个不同长度变量无法进行赋值操作。
go语言中 数组是一个值类型,使用时,直接对值进行操作,而不是地址引用。
两个长度相同的数组可以实现等于号判断。
//常规定义
var a [5]int
//简写
a:=[2]int{1,2}
//索引赋值:将最后一个元素定义为5 其余为默认值
a:=[20]int{19:5}
//自动判断数组长度定义,使用三个点 编译器将会自动判断长度赋值
a:=[...]int{11:5}
//定义指针
var p *[5]int
//定义多维数组
var arr = [2][3]int{}
arr := [2][3]int{}//GO语言冒泡排序
package main
import "fmt"
func main(){var a = [5]int{5,9,4,1,6}num := len(a)for i:=0;i<num ;i++ {for j:=i+1;j<num ;j++ {if(a[i]>a[j]){temp:=a[j]a[j] = a[i]a[i] = temp}}}fmt.Print(a)
}
切片
一、切片的定义
在Go语言中,切片(Slice)是数组的一个引用。
它会生成一个指向数组的指针,并通过切片长度关联到底层数组部分或者全部元素。
切片还提供了一系列对数组的管理功能(append、copy),可以随时动态扩充存储空间,并且可以被随意传递而不会导致所管理的数组元素被重复复制。
根据以上特征,切片通常被用来实现变长数组,而且操作灵活。
切片的数据结构原型定义如下:
src/ pkg/ runtime/ runtime. h
struct Slice
{ //must not move anythingbyte* array; //actual dataunit32 len; //number of elementsunit32 cap; //allocated number of elements
};
由切片数据结构的原型定义可以看到,它抽象为以下三个部分:
指向被引用的底层数组的指针。
切片中元素的个数。
切片分配的存储空间。
二、切片的声明与创建
切片声明与创建的方法有三种:
1、基于底层数组创建
2、直接创建
3、使用make()函数创建。
1、基于底层数组创建
在创建切片时,可以基于一个底层数组,切片可以只使用数组的一部分元素或所有元素,甚至可以创建一个比底层数组还要大的数组切片,因为切片可以动态增长。创建切片的格式如下:
var sliceName [ ]dataType
说明:
切片名的命名规则和变量名相同,遵循标识符命名规则。
在创建切片时,不要指定切片的长度。
切片的类型可以是Go语言的任何基本数据类型。
例如:
var slice1 [] int
上例中定义了一个整型切片slicel,注意不要指定切片长度,如果指定了长度就成了定义数组了。当一个切片定义好以后,如果还没有被初始化,默认值为nil, 而且切片的长度为0。切片的长度可以使用内置函数len()获取,还可以使用内置函数cap()获取切片的内存容量。
所以,当一个切片定义好以后,还要对切片进行初始化,这样切片才可用。对于上例,假如已经定义了一个整型数组array1,则切片slice1的初始化方式如下:
slice1 = array1[start : end]
从上式可以看到,Go语言支持以array1[start : end]的方式基于一个底层数组来生成切片,即切片引用的数组元素由array1[start]到 array1[end],但不包含array1[end]。
如果要引用底层数组的所有元素,可采取的方式如下:
slicel = array1
slice1 = array1[ :]
slicel = array1[0: len(array1)]
2、直接创建切片
直接创建切片,即在定义切片的时候初始化切片元素,例如:
var slice1 =[]int{1,2,3,4,5}
3、使用make函数创建切片
内置函数make()用于灵活的创建切片
var slicel = make([]int,5)
上式创建了一个有5个元素的整型切片slicel,元素的初值为0。
在使用make()函数创建切片时,还可以为切片元素预留存储空间。例如:
var slice1 = make([]int, 5,10)
上式表示,创建整型切片slice1,元素个数为5,元素初值为0,并预留10个元素的存储空间。
三、切片元素的访问与遍历
切片元素的遍历和数组元素的遍历一样,要通过元素下标访问,另外也可以使用关键字range遍历所有切片元素。切片元素访问的一般格式如下:
sliceName [sliceIndex]
遍历同数组,使用range关键字表达式,有两个返回值,第一个是元素的下标,第二个是元素的值。
四、切片的操作
1、切片元素的增加
可以使用append()函数向切片尾部添加新元素,这些元素保存到底层数组。append并不会影响原来切片的属性,它返回变更后新的切片对象。
与数组相比,除了都有长度(length)以外,切片多了一个容量(capacity)的概念,即切片中元素的个数和分配的存储空间是两个不同的值。如果在增加新元素时超出cap的限制,则底层会重新分配一块“够大”的内存,一般来说是将原来的内存空间扩大二倍,然后再将数据从原来的内存复制到新的内存块。
2、切片元素的复制
使用切片长时间引用“超大”的底层数组,会导致严重的内存浪费。可以新建一个小的slice对象,然后将所需的数据复制过去。函数copy()可以在切片之间复制元素,能够复制的数量取决于复制方和被复制方的长度值,通常取最小值。需要注意的是,在同一底层数组的不同切片间复制元素时,元素位置会发生重叠。
//切片的复制
package mainimport("fmt"
)func main() {var slicel= []int{1,2,3,4,5,6,7,8,9,10}var slice2 = make([ ] int,3, 5)var n int//只能复制三个元素n= copy(slice2,slice1)fmt. Println(n, slice2, len( slice2), cap(slice2))//slice3和slice1指向同一底层数组slice3 : = slice1[3:6]//复制后元素重叠n= copy(slice3, slice1[1:5])fmt.Println(n, slicel, slice3)
}
编译并运行程序输出结果为:3 [1 2 3] 3 5
3 [1 2 3 2 3 4 7 8 9 10] [2 3 4]
通过输出结果可以看出,在将slice1复制到slice2时,由于slice2的长度最小为3,所以只能将slice1的前三个元素复制给slice2。而将slicel1复制到slice3 时,由于slicel1和slice3指向同一个底层数组,所以复制后元素重叠。slice3刚创建时,它引用的是底层数组的[4,5,6]三个元素,复制后slice1将[2,3,4]三个元素复制给slice3 ,所以最后slice3 的元素[2,3,4]覆盖了slice1的元素[4,5,6]。
3、排序和搜索切片
标准库中的sort包提供了对整型、浮点型和字符串类型切片进行排序的函数,检查一个切片是否排序好的函数,以及使用二分搜索算法在一个有序切片中搜索-一个元素的函数。 同时提供了通用sort.Sort ()和sort.Search ()函数,可用于任何自定义的数据。这些函数在表4-2中有列出。
函数
1.简介
- 函数:为完成某一功能的程序指令(语句)的集合
- 在Go中,函数分为自定义函数、系统函数
2.基本语法
func 函数名(形参列表) (返回值列表) {函数体return 返回值列表
}
3.递归
- 函数体内调用自己
package mainimport "fmt"func test(n int) {if n > 2 {n--test(n)}fmt.Println("n = ", n)
}func main() {test(4)
}
- 执行一个函数时,就创建一个新的受保护的独立空间
- 函数的局部变量是独立的,不会相互影响
- 递归必须向退出递归的条件逼近,否则就会出现无限递归
- 当一个函数执行完毕,或者遇到
return,就会返回,遵守谁调用就将结果返回给谁。
4.递归练习
- 1.求第N个斐波那契数列对应的值
package mainimport "fmt"func feb(n int) int {if n <= 2 {return 1}return test(n-1) + test(n-2)
}func main() {result := feb(6)fmt.Println(result)
}
- 2.已知函数
f(1) = 3,f(n) = 2*f(n-1) + 1,求f(n)的值
package mainimport "fmt"func test(n int) int {if n == 1 {return 3}return 2*test(n-1) + 1
}func main() {result := test(6)fmt.Println(result)
}
- 3.有一堆桃子,猴子第一天吃了其中的一半,并在多吃了一个!以后每天猴子都吃其中的一半,然后再多吃一个。当到
第十天准备吃时,发现只剩了1个桃子。问题:最初总共多少个桃子

- 从上图可以看出其通项公式为:
(1 + f(n+1))* 2,n代表天数
package mainimport "fmt"func getPeach(n int) int {if n == 10 {return 1}return (1 + getPeach(n+1)) * 2
}func main() {result := getPeach(1)fmt.Println(result)
}
5.函数使用注意细节
-
1.函数的形参列表和返回值列表都可以是多个
-
2.形参列表和返回值列表都可以是值类型或引用类型
-
3.函数命名遵循标识符命名规则,首字母不能是数字,首字母如果是大写,则可以被其他文件或包调用,否则只能在当前文件被调用
-
4.函数的变量是局部的,函数外不生效
-
5.基本类型和数组默认都是值传递,即进行值拷贝,在函数内修改,不会影响到原来的值
-
6.如果希望函数内的变量能修改函数外的变量,可以传递变量的地址
&,函数内以指针方式操做变量 -
7.Go函数不支持重载(即一个包下不允许存在同名的函数)
-
8.在Go语言中,函数也是一种数据类型,可以赋值给一个变量,则该变量就是一个函数类型的变量,通过该变量可以对函数进行调用
-
9.函数既然是一种数据类型,因此在Go语言中,函数可以作为形参,并且调用
package mainimport "fmt"func test(myFunc func(int, int) int, num1, num2 int) int {return myFunc(num1, num2) }func getSum(a, b int) int {return a + b } func main() {resp := test(getSum, 1, 2)fmt.Println(resp) } -
10.为了简化数据类型定义,Go语言支持自定义数据类型
- 基本语法:
type myInt int,myInt就可以当作int类型来使用,但不完全一致,不能将一个myInt类型的值直接赋值给int类型的变量,需要使用int()来强转一下。 - 也可以使用type来定义一个函数类型
package mainimport "fmt"type myFuncType func(int, int) intfunc test(myFunc myFuncType, num1, num2 int) int {return myFunc(num1, num2) }func getSum(a, b int) int {return a + b }func main() {resp := test(getSum, 1, 2)fmt.Println(resp) } - 基本语法:
-
11.支持对函数返回值命名
package mainimport "fmt"type myFuncType func(int, int) intfunc test(myFunc myFuncType, num1, num2 int) int {return myFunc(num1, num2) }// 将函数返回值重命名为sum func getSum(a, b int) (sum int) {sum = a + breturn }func main() {resp := test(getSum, 1, 2)fmt.Println(resp) } -
12.使用
_来忽略返回值 -
13.Go支持可变参数
参数名 ...,必须放在参数最后位置package mainimport "fmt"func getSum(args ...int) int {sum := 0for i := 0; i < len(args); i++ {sum += args[i]}return sum } func main() {resp := getSum(1, 2, 3)fmt.Println(resp) }
6.init函数
- 每个源文件都可以包含一个init函数,该函数会在
main函数前执行,被Go运行框架调用。 - 通常在init函数中完成初始化工作,每个文件都可以有一个init函数
package mainimport "fmt"func init() {fmt.Println("init函数自动执行") }func main() {fmt.Println("开始执行主函数") } - 如果一个文件中同时包含
全局变量、init函数、main函数,则执行顺序为:全局变量 > init > mainpackage mainimport "fmt"var money = test()func test() int {fmt.Println("test()")return 100 }func init() {fmt.Println("init函数自动执行") }func main() {fmt.Println("开始执行主函数...money=", money) }// test() // init函数自动执行 // 开始执行主函数...money= 100
7.匿名函数
- Go支持匿名函数,如果我们某个函数只希望使用一次,可以考虑使用匿名函数,匿名函数可以实现多次调用
- 示例一:在定义时就调用
package mainimport "fmt"func main() {res := func(n1, n2 int) int {return n1 + n2}(10, 20)fmt.Println("result =", res) } - 示例二:将匿名函数赋值给一个变量(函数变量),再通过该变量来调用匿名函数
package mainimport "fmt"func main() {sum := func(n1, n2 int) int {return n1 + n2}res := sum(10, 20)fmt.Println("result =", res) } - 示例三:全匿名函数,将函数赋值给一个全局变量,就成为一个全局函数,可以在程序有效
package mainimport "fmt"var multi = func(n1, n2 int) int {return n1 * n2 }func main() {res := multi(10, 20)fmt.Println("result =", res) }
8.闭包
-
闭包就是一个
函数和与其相关的引用环境组合的一个整体 -
闭包必须满足三个条件:
1、必须有一个内嵌函数
2、内嵌函数必须引用外部函数中的变量
3、外部函数返回值必须是内嵌函数 -
闭包可以使得变量常驻内存
package mainimport "fmt"func Closure() func(int) int {var n1 = 10return func(n2 int) int {n1 = n1 + n2return n1// return n1 + n2 // 这样的结果完全不一样, n1 = n1 + n2会修改局部变量n1的值,如果直接返回n1 + n2,则不会修改局部变量n1的值} }func main() {res := Closure()fmt.Println("result =", res(30)) // 40fmt.Println("result =", res(31)) // 71 } -
nodejsfunction closure() { var a = 10; function inner(b) {a = a + b; return a} return inner; } var func = closure(); console.log(func(30)); // 40 console.log(func(31)); // 71 -
python# 变量 a 对于 inner来说是外部变量,因此不能直接进行修改 def closure():a = 10def inner(b):a = a + breturn areturn inner# UnboundLocalError: local variable 'a' referenced before assignment# 但对于inner来说是可以直接使用的 def closure():a = 10def inner(b):return a + breturn inner# 必须使用 nonlocal 来修改变量a的作用域,从而对其进行操做 def closure():a = 10def inner(b):nonlocal aa = a + breturn areturn innerfunc = closure() print(func(30)) # 40 print(func(31)) # 71 -
案例:使用闭包方式,实现检查文件后缀名是否为
.jpg,如果不是,则内部实现拼接.jpg,否则直接返回package mainimport ("fmt""strings" )func Closure(endFix string) func(string) string {return func(name string) string {if strings.HasSuffix(name, endFix) {return name}return name + endFix} }func main() {res := Closure(".jpg")fmt.Println("result =", res("aaa.jpg"))fmt.Println("result =", res("bbb")) }
9.函数参数传递
- 值类型:基本数据类型:int系列、float系列、bool、string、数组、结构体
- 引用类型:指针、slice切片、map、管道chan、interface等
结构体
结构体是一种用户自定义的数据类型,它由一组字段组成,每个字段可以是任意基本类型或其他结构体类型。结构体在Go语言中被广泛使用,它可以用来表示复杂的数据结构,比如二叉树、链表、图等。
一个简单的结构体定义如下:
copy codetype Person struct {name stringage intgender string
}
上面的代码定义了一个名为Person的结构体,它有三个字段,分别是name、age和gender,它们的类型分别为string、int和string。我们可以通过该结构体来表示一个人的基本信息。
1.结构体的语法
Go语言中结构体的语法非常简洁,它的基本形式如下:
copy codetype 结构体名 struct {字段1 类型1字段2 类型2...字段n 类型n
}
其中,结构体名是用户自定义的标识符,用于表示该结构体的类型。字段是结构体中的成员,每个字段都有一个对应的类型。在定义结构体时,可以使用任何基本类型或其他结构体类型作为字段的类型。另外,结构体中的字段可以使用大写字母开头的标识符表示公有成员,小写字母开头的标识符表示私有成员。
2.结构体的初始化
在Go语言中,结构体类型的变量可以通过结构体字面量来进行初始化。结构体字面量是一种简洁的语法,可以用于快速创建一个结构体类型的变量。结构体字面量的基本形式如下:
copy codevar 变量名 = 结构体类型{字段1: 值1,字段2: 值2,...字段n: 值n,
}
其中,变量名是结构体类型的变量名,结构体类型是用户自定义的结构体类型,字段是结构体中的成员,值是该成员对应的初始化值。我们可以省略字段名,只提供值,此时Go语言会按照结构体定义时的字段顺序来进行初始化。例如:
copy codevar p1 = Person{"张三",18,"男",
}var p2 = Person{name: "李四",age: 20,gender: "女",
}
上面的代码分别创建了两个Person类型的变量p1和p2,它们的字段值分别为{张三 18 男}和{李四 20 女}。可以看出,结构体字面量提供了一种简单、直观的方式来初始化结构体类型的变量。
3.结构体的访问
在Go语言中,我们可以通过结构体变量的字段名来访问结构体中的成员。例如:
copy codevar p Person
p.name = "张三"
p.age = 18
p.gender = "男"
上面的代码创建了一个名为p的Person类型的变量,并对其成员进行了赋值。可以看出,访问结构体成员的语法非常简单,只需要使用点号(.)连接结构体变量和成员名即可。
4.结构体的方法
Go语言中的结构体还支持方法,方法是一种特殊的函数,它可以与结构体类型关联。方法与函数的区别在于,方法必须在结构体类型上定义,而函数可以在任何地方定义。另外,方法可以访问结构体的成员,而函数只能访问其参数。
Go语言中的方法定义如下:
copy codefunc (接收者变量 接收者类型) 方法名(参数列表) 返回值列表 {// 方法体
}
其中,接收者变量是一个标识符,用于表示方法所属的结构体类型的变量。接收者类型是方法所属的结构体类型,参数列表和返回值列表与普通函数的定义方式相同。
下面是一个例子:
copy codetype Rectangle struct {width, height float64
}func (r Rectangle) Area() float64 {return r.width * r.height
}func main() {r := Rectangle{3, 4}fmt.Println("面积:", r.Area())
}
上面的代码定义了一个名为Rectangle的结构体,它有两个字段width和height。该结构体还定义了一个名为Area的方法,用于计算矩形的面积。在main函数中,我们创建了一个Rectangle类型的变量r,并调用其Area方法来计算面积。
5.结构体的嵌套
在Go语言中,结构体可以嵌套在其他结构体中,从而形成更复杂的数据结构。嵌套结构体的定义方式与普通结构体的定义方式相同,只是在字段的类型中指定另一个结构体类型。
下面是一个例子:
copy codetype Address struct {Province stringCity string
}type Person struct {Name stringAge intAddress Address
}func main() {p := Person{Name: "张三",Age: 18,Address: Address{Province: "广东省",City: "深圳市",},}fmt.Println(p)
}
上面的代码定义了两个结构体类型,Address和Person。Person结构体中包含一个Address类型的字段,用于表示该人员的地址信息。在main函数中,我们创建了一个Person类型的变量p,并对其成员进行了赋值。可以看出,嵌套结构体提供了一种简单、灵活的方式来表示复杂的数据结构。
6.结构体的匿名字段
在Go语言中,结构体还支持匿名字段。匿名字段是一种特殊的字段类型,它没有字段名,只有字段类型。在结构体中,可以使用匿名字段来表示继承关系或者组合关系。
下面是一个例子:
copy codetype Person struct {stringint
}func main() {p := Person{"张三", 18}fmt.Println(p.string, p.int)
}
上面的代码定义了一个Person结构体,它包含了一个string类型的匿名字段和一个int类型的匿名字段。在main函数中,我们创建了一个Person类型的变量p,并对其成员进行了访问。可以看出,使用匿名字段可以在一定程度上简化代码。
7.结构体的标签
在Go语言中,结构体的字段可以使用标签(tag)来进行注释或者元数据的传递。标签是一个字符串,它的格式为key:"value",其中key表示标签的名称,value表示标签的值。
下面是一个例子:
copy codetype Person struct {Name string `json:"name"`Age int `json:"age"`
}func main() {p := Person{"张三", 18}b, _ := json.Marshal(p)fmt.Println(string(b))
}
上面的代码定义了一个Person结构体,它有两个字段Name和Age。在Name字段和Age字段上,我们使用了json标签,用于指定json序列化时使用的字段名。在main函数中,我们创建了一个Person类型的变量p,并将其序列化为json字符串。可以看出,使用标签可以方便地进行元数据传递和注释。
8.结构体的应用场景
在Go语言中,结构体被广泛应用于各种数据结构的定义和实现。下面是一些常见的应用场景:
- 数据库ORM:结构体可以与数据库表进行映射,从而实现对象关系映射(ORM)功能。
- 网络编程:结构体可以用于表示网络数据包的格式,从而实现网络编程功能。
- 并发编程:结构体可以用于实现并发编程模型,例如管道、锁和条件变量等。
- 配置文件:结构体可以用于表示配置文件的格式,从而实现配置文件读写功能。
- 模板引擎:结构体可以用于表示模板数据,从而实现模板引擎功能。
相关文章:
Go语言基础
Go的数据类型定义 //运行第一个程序package main func main(){print("Hello World") }在GO语言中,一个程序只能有一个main包,对应只能有一个main方法,若无法满足这个条件,编译时将会报错。注释方式与PHP相同 import的使…...
IOS覆盖率报告info文件解读
一,IOS覆盖率报告的生成 在做前端精准测试的时候,对于iOS端,通常会做如下操作: (1)合并覆盖率数据 如下操作: xcrun llvm-profdata merge coverage_file1657885040728.profraw coverage_fil…...
爬虫实战——scrapy框架爬取多张图片
scrapy框架的基本使用,请参考我的另一篇文章:scrapy框架的基本使用 起始爬取的网页如下: 点击每张图片,可以进入图片的详情页,如下: 代码实现: 项目文件结构如下 img_download.py文件代码 im…...
LLVM TableGen 系统学习笔记
Basic TableGen 系统可以帮助记录领域特定的信息。它也可以认为是一种小型的编译系统。 TableGen 责负分析文件, 分析结果交给领域特定的后端进行处理。 重要的概念 records 一个 record 有一个独立的名称,一系列值和一系列父类。 它保存了特定领域…...
基于stm32的流水灯设计
1基于stm32的流水灯设计[proteus仿真] 速度检测系统这个题目算是课程设计和毕业设计中常见的题目了,本期是一个基于51单片机的自行车测速系统设计 需要的源文件和程序的小伙伴可以关注公众号【阿目分享嵌入式】,赞赏任意文章 2¥,…...
kotlin图片合成和压缩
kotlin图片合成和压缩 之前的方法是继承AsyncTask 在doInBackground 里面去做压缩的操作,然后用 publishProgress 切到主线程里面更新 新方法是在协程里的去做 class ImageService {private fun getSumWidths(bitmaps: ArrayList<Bitmap>): Int {var sumWid…...
Java学习笔记004——接口概念理解及意义
一个类中有抽象方法,则必须声明为abstract(做为抽象类),抽象类不能实例化。子类继承抽象类,必须对所有的抽象方法重写,否则依然有抽象方法,还是抽象的,无法实例化。故抽象类常做为基…...
MT笔试题
前言 某团硬件工程师的笔试题,个人感觉题目的价值还是很高的,分为选择题和编程题,选择题考的是嵌入式基础知识,编程题是两道算法题,一道为简单难度,一道为中等难度 目录 前言选择题编程题 选择题 C语言中变…...
50道SQL面试题
50道SQL面试题 有需要互关的小伙伴,关注一下,有关必回关,争取今年认证早日拿到博客专家 环境 -- ---------------------------- -- Table structure for teacher -- ---------------------------- DROP TABLE IF EXISTS teacher; CREATE TABLE teacher (t_id varchar(20) …...
2024蓝桥杯每日一题(双指针)
一、第一题:牛的学术圈 解题思路:双指针贪心 仔细思考可以知道,写一篇综述最多在原来的H指数的基础上1,所以基本方法可以是先求出原始的H指数,然后分类讨论怎么样提升H指数。 【Python程序代码】 n,l map(int,…...
Android 开发过程中常见的内存泄漏场景分析
场景1 Static变量存储上下文环境Context public class ClassName {// 定义1个静态变量private static Context mContext;//... // 引用的是Activity的contextmContext context; // 当Activity需销毁时,由于mContext 静态 & 生命周期 应用程序的生命周期&…...
Codeforces-1935E:Distance Learning Courses in MAC(思维)
E. Distance Learning Courses in MAC time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output The New Year has arrived in the Master’s Assistance Center, which means it’s time to introduce a new feature…...
ZooKeeper和Diamond有什么不同
本文主要是讨论下两个类似产品:ZooKeeper和Diamond在配置管理这个应用场景上的异同点。 Diamond,顾名思义,寄寓了开发人员对产品稳定性的厚望,希望它像钻石一样,提供稳定的配置访问。Diamond是淘宝网Java中间件团队的核…...
三、N元语法(N-gram)
为了弥补 One-Hot 独热编码的维度灾难和语义鸿沟以及 BOW 词袋模型丢失词序信息和稀疏性这些缺陷,将词表示成一个低维的实数向量,且相似的词的向量表示是相近的,可以用向量之间的距离来衡量相似度。 N-gram 统计语言模型是用来计算句子概率的…...
QML 3D入门知识路线
目前使用的版本 v5.14.0 模块导入 使用QML 3D时需要 import Qt3D.Core 2.14 核心模块类 V6以上的版本已经发布,所以有很多module会发生变化,主要有核心module、输入、逻辑、渲染、动画和扩展module,以及2D/3D场景模块 类名 能…...
蓝牙系列五:开源蓝牙协议BTStack框架代码阅读(1)
蓝牙学习系列,借鉴卫东上老师的蓝牙视频教程。 BTStack协议栈学习。首先来看一下,对于硬件操作,它是如何来进行处理的。在上篇文章中曾说过,在main函数里面它会调用硬件相关的代码,调用操作系统相关的代码。在BTStack中,可以搜索一下main.c,将会发现有很多main.c,都是…...
c++ 类内可以定义引用数据成员吗?
在C中,类内是可以定义引用数据成员的,但是在初始化对象时,必须在构造函数的成员初始化列表中对引用进行初始化,因为引用必须在创建时被初始化,并且不能在其生存期内引用不同的对象。下面是一个简单的示例: …...
MacBook2024苹果免费mac电脑清理垃圾软件CleanMyMac X
CleanMyMac X是一款专业的Mac清理软件,具备多种强大功能。首先,它能够智能清理Mac磁盘上的垃圾文件和多余语言安装包,从而快速释放电脑内存。其次,CleanMyMac X可以轻松管理和升级Mac上的应用,同时强力卸载恶意软件并修…...
Vue.js计算属性:实现数据驱动的利器
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…...
10-ARM gicv3/gicv4的总结-基础篇
目录 1、gic的版本2、GICv3/gicv4的模型图3、gic中断号的划分4、GIC连接方式5、gic的状态6、gic框架7、gic Configuring推荐 本文转自 周贺贺,baron,代码改变世界ctw,Arm精选, armv8/armv9,trustzone/tee,s…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...
vue3 daterange正则踩坑
<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...
