Gogo学习笔记1hello GO 这里使用vscode 安装插件go 新建hello文件夹,创建main.go文件 package main import "fmt" func main(){ fmt.Println("Hello") } 打开命令行 执行go build 这时同目录会创建一个hello.exe的文件(我这里使用的是win电脑) 也可以使用 go build作者王明昌发布时间2020-08-27文章目录hello GO跨平台编译基础变量和常量数据类型运算符流程控制数组切片maphello GO 这里使用vscode 安装插件go新建hello文件夹,创建main.go文件 复制package main import "fmt" func main(){ fmt.Println("Hello") } 打开命令行 执行go build 这时同目录会创建一个hello.exe的文件(我这里使用的是win电脑) 也可以使用 go build -o aaa.exe 指定文件名也直接输出可使用 go run main.go 跨平台编译 只需要指定目标操作系统的平台和处理器架构即可: 复制SET CGO_ENABLED=0 // 禁用CGO SET GOOS=linux // 目标平台是linux SET GOARCH=amd64 // 目标处理器架构是amd64 然后再执行go build命令,得到的就是能够在Linux平台运行的可执行文件了。 Mac 下编译 Linux 和 Windows平台 64位 可执行程序: 复制CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build Linux 下编译 Mac 和 Windows 平台64位可执行程序: 复制CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build Windows下编译Mac平台64位可执行程序: 复制SET CGO_ENABLED=0 SET GOOS=darwin SET GOARCH=amd64 go build 基础 //单行注释 /* 多行注释 */ fmt.Println('打印输出') 一行代码不需加分号 变量声明后必须使用,不使用会报错 缩进没有严格要求 变量和常量标书与关键字 Go语言中标识符由字母数字和_(下划线)组成,并且只能以字母和_开头。 关键词 25个关键词 复制 break default func interface select case defer go map struct chan else goto package switch const fallthrough if range type continue for import return var 37个保留词 复制 Constants: true false iota nil Types: int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr float32 float64 complex128 complex64 bool byte rune string error Functions: make len cap new append copy close delete complex real imag panic recover 变量 声明: var 变量名 变量类型复制单个声明 var aaa string var age int var iss bool 批量声明 var ( a string b int c bool ) 变量初始化: var 变量名 类型 = 表达式复制var name string = "aa" 一次初始化多个变量 var name,age = "bb",20 短变量声明(声明并初始化) :=复制n:=10 m:=50 匿名变量:用一个下划线_表示 匿名变量不占用命名空间,不会分配内存,所以匿名变量之间不存在重复声明。 (在Lua等编程语言里,匿名变量也被叫做哑元变量。) 复制func foo() (int, string) { return 10, "Q1mi" } func main() { x, _ := foo() _, y := foo() fmt.Println("x=", x) fmt.Println("y=", y) } 注意: 函数外的每个语句都必须以关键字开始(var、const、func等) :=不能使用在函数外。 _多用于占位,表示忽略值。 常量constconst a = 'dsadasd' 和变量类似 复制const ( a string b int c bool ) iota : go语言的常量计数器 iota在const关键字出现时将被重置为0 复制const ( n1 = iota //0 n2 //1 n3 //2 n4 //3 ) 使用_调过某些值 const ( n1 = iota //0 n2 //1 _ n4 //3 ) iota声明中间插队 复制const ( n1 = iota //0 n2 = 100 //100 n3 = iota //2 n4 //3 ) const n5 = iota //0 多个iota定义在一行 复制const ( a, b = iota + 1, iota + 2 //1,2 c, d //2,3 e, f //3,4 ) 数据类型整型 Go语言中有丰富的数据类型,除了基本的整型、浮点型、布尔型、字符串外,还有数组、切片、结构体、函数、map、通道(channel)等。 类型描述uint8无符号 8位整型 (0 到 255)uint16无符号 16位整型 (0 到 65535)uint32无符号 32位整型 (0 到 4294967295)uint64无符号 64位整型 (0 到 18446744073709551615)int8有符号 8位整型 (-128 到 127)int16有符号 16位整型 (-32768 到 32767)int32有符号 32位整型 (-2147483648 到 2147483647)int64有符号 64位整型 (-9223372036854775808 到 9223372036854775807) 特殊整型 类型描述uint32位操作系统上就是uint32,64位操作系统上就是uint64int32位操作系统上就是int32,64位操作系统上就是int64uintptr无符号整型,用于存放一个指针 进制 复制 // 十进制 var a int = 10 fmt.Printf("%d \n", a) // 10 fmt.Printf("%b \n", a) // 1010 占位符%b表示二进制 // 八进制 以0开头 var b int = 077 fmt.Printf("%o \n", b) // 77 // 十六进制 以0x开头 var c int = 0xff fmt.Printf("%x \n", c) // ff fmt.Printf("%X \n", c) // FF 浮点型 Go语言支持两种浮点型数:float32和float64复制package main import ( "fmt" "math" ) func main() { fmt.Printf("%f\n", math.Pi) fmt.Printf("%.2f\n", math.Pi) } 复数 complex64和complex128 复数有实部和虚部,complex64的实部和虚部为32位,complex128的实部和虚部为64位。 复制var c1 complex64 c1 = 1 + 2i var c2 complex128 c2 = 2 + 3i fmt.Println(c1) fmt.Println(c2) 布尔值 Go语言中以bool类型进行声明布尔型数据,布尔型数据只有true(真)和false(假)两个值。 注意:布尔类型变量的默认值为false。Go 语言中不允许将整型强制转换为布尔型.布尔型无法参与数值运算,也无法与其他类型进行转换。字符串复制s1 := "hello" s2 := "你好" 字符串转义符 转义符含义\r回车符(返回行首)\n换行符(直接跳到下一行的同列位置)\t制表符\'单引号\"双引号\\反斜杠 多行字符串 使用反引号 字符串的常用操作 方法介绍len(str)求长度+或fmt.Sprintf拼接字符串strings.Split分割strings.contains判断是否包含strings.HasPrefix,strings.HasSuffix前缀/后缀判断strings.Index(),strings.LastIndex()子串出现的位置strings.Join(a[]string, sep string)join操作byte和rune类型 字符用单引号(’)包裹起来 nt8类型,或者叫 byte 型,代表了ASCII码的一个字符。rune类型,代表一个 UTF-8字符。 当需要处理中文、日文或者其他复合字符时,则需要用到rune类型。rune类型实际是一个int32 修改字符串 要修改字符串,需要先将其转换成[]rune或[]byte,完成后再转换为string。无论哪种转换,都会重新分配内存,并复制字节数组。 复制func changeString() { s1 := "big" // 强制类型转换 byteS1 := []byte(s1) byteS1[0] = 'p' fmt.Println(string(byteS1)) s2 := "白萝卜" runeS2 := []rune(s2) runeS2[0] = '红' fmt.Println(string(runeS2)) } 类型转换 强制转换 复制T(表达式) T表示要转换的类型。表达式包括变量、复杂算子和函数返回值等. 运算符算术运算符 + - * / %关系运算符 == != > >= < <=逻辑运算符&& || !位运算符运算符描述&参与运算的两数各对应的二进位相与。 (两位均为1才为1)|参与运算的两数各对应的二进位相或。 (两位有一个为1就为1)^参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。 (两位不一样则为1)<<左移n位就是乘以2的n次方。 “a<>>右移n位就是除以2的n次方。 “a>>b”是把a的各二进位全部右移b位。赋值运算符= += -= *= /= %= <<= >>= &= |= ^=流程控制ifelse复制if 表达式1 { 分支1 } else if 表达式2 { 分支2 } else{ 分支3 } for复制for 初始语句;条件表达式;结束语句{ 循环体语句 } 复制完整 func forDemo() { for i := 0; i < 10; i++ { fmt.Println(i) } } 初始语句省略 func forDemo2() { i := 0 for ; i < 10; i++ { fmt.Println(i) } } 初始语句/结束语句结束 func forDemo3() { i := 0 for i < 10 { fmt.Println(i) i++ } } 无限循环 for { 循环体语句 } for range(键值循环)switch case复制func switchDemo1() { finger := 3 switch finger { case 1: fmt.Println("大拇指") case 2: fmt.Println("食指") case 3: fmt.Println("中指") case 4: fmt.Println("无名指") case 5: fmt.Println("小拇指") default: fmt.Println("无效的输入!") } } func testSwitch3() { switch n := 7; n { case 1, 3, 5, 7, 9: fmt.Println("奇数") case 2, 4, 6, 8: fmt.Println("偶数") default: fmt.Println(n) } } fallthrough语法可以执行满足条件的case的下一个case,是为了兼容C语言中的case设计的。 复制func switchDemo5() { s := "a" switch { case s == "a": fmt.Println("a") fallthrough case s == "b": fmt.Println("b") case s == "c": fmt.Println("c") default: fmt.Println("...") } } 输出: a b goto 通过标签进行代码间的无条件跳转 复制func gotoDemo2() { for i := 0; i < 10; i++ { for j := 0; j < 10; j++ { if j == 2 { // 设置退出标签 goto breakTag } fmt.Printf("%v-%v\n", i, j) } } return // 标签 breakTag: fmt.Println("结束for循环") } break(跳出循环)break语句可以结束for、switch和select的代码块。 复制func breakDemo1() { BREAKDEMO1: for i := 0; i < 10; i++ { for j := 0; j < 10; j++ { if j == 2 { break BREAKDEMO1 } fmt.Printf("%v-%v\n", i, j) } } fmt.Println("...") } continue(继续下次循环)复制func continueDemo() { forloop1: for i := 0; i < 5; i++ { // forloop2: for j := 0; j < 5; j++ { if i == 2 && j == 2 { continue forloop1 } fmt.Printf("%v-%v\n", i, j) } } } 数组数组定义var 数组变量名 [元素数量]T 一旦定义,长度不能变 初始化复制func main() { var testArray [3]int //数组会初始化为int类型的零值 var numArray = [3]int{1, 2} //使用指定的初始值完成初始化 var cityArray = [3]string{"北京", "上海", "深圳"} //使用指定的初始值完成初始化 fmt.Println(testArray) //[0 0 0] fmt.Println(numArray) //[1 2 0] fmt.Println(cityArray) //[北京 上海 深圳] } 复制func main() { var testArray [3]int var numArray = [...]int{1, 2} var cityArray = [...]string{"北京", "上海", "深圳"} fmt.Println(testArray) //[0 0 0] fmt.Println(numArray) //[1 2] fmt.Printf("type of numArray:%T\n", numArray) //type of numArray:[2]int fmt.Println(cityArray) //[北京 上海 深圳] fmt.Printf("type of cityArray:%T\n", cityArray) //type of cityArray:[3]string } 复制func main() { a := [...]int{1: 1, 3: 5} fmt.Println(a) // [0 1 0 5] fmt.Printf("type of a:%T\n", a) //type of a:[4]int } 数组遍历复制func main() { var a = [...]string{"北京", "上海", "深圳"} // 方法1:for循环遍历 for i := 0; i < len(a); i++ { fmt.Println(a[i]) } // 方法2:for range遍历 for index, value := range a { fmt.Println(index, value) } } 多维数组复制func main() { a := [3][2]string{ {"北京", "上海"}, {"广州", "深圳"}, {"成都", "重庆"}, } for _, v1 := range a { for _, v2 := range v1 { fmt.Printf("%s\t", v2) } fmt.Println() } } 北京 上海 广州 深圳 成都 重庆 多维数组只有第一层可以使用...来让编译器推导数组长度。例如: 复制//支持的写法 a := [...][2]string{ {"北京", "上海"}, {"广州", "深圳"}, {"成都", "重庆"}, } //不支持多维数组的内层使用... b := [3][...]string{ {"北京", "上海"}, {"广州", "深圳"}, {"成都", "重庆"}, } 数组是值类型 数组是值类型,赋值和传参会复制整个数组。因此改变副本的值,不会改变本身的值。 复制func modifyArray(x [3]int) { x[0] = 100 } func modifyArray2(x [3][2]int) { x[2][0] = 100 } func main() { a := [3]int{10, 20, 30} modifyArray(a) //在modify中修改的是a的副本x fmt.Println(a) //[10 20 30] b := [3][2]int{ {1, 1}, {1, 1}, {1, 1}, } modifyArray2(b) //在modify中修改的是b的副本x fmt.Println(b) //[[1 1] [1 1] [1 1]] } 注意:数组支持 “==“、”!=” 操作符,因为内存总是被初始化过的。[n]*T表示指针数组,*[n]T表示数组指针 。切片 一个拥有相同类型元素的可变长度的序列 定义var name []T长度/容量 通过使用内置的len()函数求长度,使用内置的cap()函数求切片的容量 复制len(s), cap(s) 使用make()函数创建构造切片复制make([]T, size, cap) T:切片的元素类型 size:切片中元素的数量 cap:切片的容量 a := make([]int, 2, 10) fmt.Println(a) //[0 0] fmt.Println(len(a)) //2 fmt.Println(cap(a)) //10 判断切片是否为空 请始终使用len(s) == 0来判断,而不应该使用s == nil来判断。 切片不能直接比较切片赋值拷贝复制s1 := make([]int, 3) //[0 0 0] s2 := s1 //将s1直接赋值给s2,s1和s2共用一个底层数组 切片遍历 遍历方式和数组是一致的 append复制func main(){ var s []int s = append(s, 1) // [1] s = append(s, 2, 3, 4) // [1 2 3 4] s2 := []int{5, 6, 7} s = append(s, s2...) // [1 2 3 4 5 6 7] } var声明的零值切片可以在append()函数直接使用,无需初始化。 复制s := []int{} // 没有必要初始化 s = append(s, 1, 2, 3) var s = make([]int) // 没有必要初始化 s = append(s, 1, 2, 3) 追加切片 复制var citySlice []string // 追加一个元素 citySlice = append(citySlice, "北京") // 追加多个元素 citySlice = append(citySlice, "上海", "广州", "深圳") // 追加切片 a := []string{"成都", "重庆"} citySlice = append(citySlice, a...) fmt.Println(citySlice) //[北京 上海 广州 深圳 成都 重庆] copy复制copy(destSlice, srcSlice []T) srcSlice: 数据来源切片 destSlice: 目标切片 复制func main() { // copy()复制切片 a := []int{1, 2, 3, 4, 5} c := make([]int, 5, 5) copy(c, a) //使用copy()函数将切片a中的元素复制到切片c fmt.Println(a) //[1 2 3 4 5] fmt.Println(c) //[1 2 3 4 5] c[0] = 1000 fmt.Println(a) //[1 2 3 4 5] fmt.Println(c) //[1000 2 3 4 5] } 删除元素 没有删除切片元素的专用方法,我们可以使用切片本身的特性来删除元素 从切片a中删除索引为index的元素,操作方法是a = append(a[:index], a[index+1:]...)复制func main() { // 从切片中删除元素 a := []int{30, 31, 32, 33, 34, 35, 36, 37} // 要删除索引为2的元素 a = append(a[:2], a[3:]...) fmt.Println(a) //[30 31 33 34 35 36 37] } mapmap定义复制map[KeyType]ValueType KeyType:表示键的类型。 ValueType:表示键对应的值的类型。 map类型的变量默认初始值为nil,需要使用make()函数来分配内存。语法为: 复制make(map[KeyType]ValueType, [cap]) 基本使用复制func main() { scoreMap := make(map[string]int, 8) scoreMap["张三"] = 90 scoreMap["小明"] = 100 fmt.Println(scoreMap) fmt.Println(scoreMap["小明"]) fmt.Printf("type of a:%T\n", scoreMap) } map[小明:100 张三:90] 100 type of a:map[string]int map也支持在声明的时候填充元素 func main() { userInfo := map[string]string{ "username": "沙河小王子", "password": "123456", } fmt.Println(userInfo) // } 判断某个键是否存在复制value, ok := map[key] 复制func main() { scoreMap := make(map[string]int) scoreMap["张三"] = 90 scoreMap["小明"] = 100 // 如果key存在ok为true,v为对应的值;不存在ok为false,v为值类型的零值 v, ok := scoreMap["张三"] if ok { fmt.Println(v) } else { fmt.Println("查无此人") } } map遍历复制func main() { scoreMap := make(map[string]int) scoreMap["张三"] = 90 scoreMap["小明"] = 100 scoreMap["娜扎"] = 60 for k, v := range scoreMap { fmt.Println(k, v) } } 遍历map时的元素顺序与添加键值对的顺序无关。 delete复制delete(map, key) 复制func main(){ scoreMap := make(map[string]int) scoreMap["张三"] = 90 scoreMap["小明"] = 100 scoreMap["娜扎"] = 60 delete(scoreMap, "小明")//将小明:100从map中删除 for k,v := range scoreMap{ fmt.Println(k, v) } } 按照指定顺序遍历map复制func main() { rand.Seed(time.Now().UnixNano()) //初始化随机数种子 var scoreMap = make(map[string]int, 200) for i := 0; i < 100; i++ { key := fmt.Sprintf("stu%02d", i) //生成stu开头的字符串 value := rand.Intn(100) //生成0~99的随机整数 scoreMap[key] = value } //取出map中的所有key存入切片keys var keys = make([]string, 0, 200) for key := range scoreMap { keys = append(keys, key) } //对切片进行排序 sort.Strings(keys) //按照排序后的key遍历map for _, key := range keys { fmt.Println(key, scoreMap[key]) } } 元素为map类型的切片复制func main() { var mapSlice = make([]map[string]string, 3) for index, value := range mapSlice { fmt.Printf("index:%d value:%v\n", index, value) } fmt.Println("after init") // 对切片中的map元素进行初始化 mapSlice[0] = make(map[string]string, 10) mapSlice[0]["name"] = "小王子" mapSlice[0]["password"] = "123456" mapSlice[0]["address"] = "沙河" for index, value := range mapSlice { fmt.Printf("index:%d value:%v\n", index, value) } } 值为切片类型的map复制func main() { var sliceMap = make(map[string][]string, 3) fmt.Println(sliceMap) fmt.Println("after init") key := "中国" value, ok := sliceMap[key] if !ok { value = make([]string, 0, 2) } value = append(value, "北京", "上海") sliceMap[key] = value fmt.Println(sliceMap)
2020-02-08go环境搭建1. 在 ~ 下创建 go 文件夹,并进入 go 文件夹 mkdir ~/go && cd ~/go 2. 下载的 go 压缩包 wget https://dl.google.com/go/go1.1
2023-08-15学习go语言第二天数组切片 数组 - 定长序列,声明时需要指定长度: var arr [5]int arr[0] = 1 arr[1] = 2 fmt.Println(arr) // [1 2 0 0 0] arr2
2023-08-16学习go语言Day3接口 学习接口interface的使用,进行抽象和多态实现。学会定义接口实现结构体。 在Go语言中,接口(interface)主要用于抽象和多态实现,使用方式如下: 定义接口 接口使用type和接口命
2023-08-17学习go语言Day4测试 学习错误处理和测试框架,可以编写简单的单元测试。 Go语言中的错误处理和测试框架主要可以学习以下两方面: 错误处理 Go通过返回错误值来表示错误。 可以通过errors.New构造错误对象。 使
2023-08-13PHP和Go语言在语法上有什么不同PHP和Go语言在语法上有以下一些主要不同点: 变量声明 PHP是动态类型,变量由$标识,无需声明类型。Go是静态强类型,变量需要声明明确类型。 代码结构 PHP可以在代码任意位置直接执行代码。Go需
2023-08-13使用Claude给自己制定两周学习Go语言计划第一周: Day1:学习Go语言环境安装,编写Hello World程序,学习基本语法、变量声明。 Day2:学习Go语言基本数据类型、数组切片,流程控制、函数使用。编写简单算法程序。 Day3:学习