这里使用vscodelinux
安装插件go编程
新建hello文件夹,建立main.go文件windows
package main import "fmt" func main(){ fmt.Println("Hello") }
打开命令行数组
执行go build 这时同目录会建立一个hello.exe的文件(我这里使用的是win电脑)bash
也可使用 go build -o aaa.exe 指定文件名架构
也直接输出可以使用 go run main.goapp
只须要指定目标操做系统的平台和处理器架构便可:编程语言
SET CGO_ENABLED=0 // 禁用CGO SET GOOS=linux // 目标平台是linux SET GOARCH=amd64 // 目标处理器架构是amd64
而后再执行go build
命令,获得的就是可以在Linux平台运行的可执行文件了。函数
Mac 下编译 Linux 和 Windows平台 64位 可执行程序:oop
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等)
:=
不能使用在函数外。
_
多用于占位,表示忽略值。
const 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) |
特殊整型
类型 | 描述 |
---|---|
uint | 32位操做系统上就是uint32 ,64位操做系统上就是uint64 |
int | 32位操做系统上就是int32 ,64位操做系统上就是int64 |
uintptr | 无符号整型,用于存放一个指针 |
进制
// 十进制 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
。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操做 |
字符用单引号(’)包裹起来
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<<b”是把a的各二进位所有左移b位,高位丢弃,低位补0。 |
>> | 右移n位就是除以2的n次方。 “a>>b”是把a的各二进位所有右移b位。 |
赋值运算符 = += -= *= /= %= <<= >>= &= |= ^=
if 表达式1 { 分支1 } else if 表达式2 { 分支2 } else{ 分支3 }
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 { 循环体语句 }
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
经过标签进行代码间的无条件跳转
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
语句能够结束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("...") }
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([]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共用一个底层数组
遍历方式和数组是一致的
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(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] }
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("查无此人") } }
func main() { scoreMap := make(map[string]int) scoreMap["张三"] = 90 scoreMap["小明"] = 100 scoreMap["娜扎"] = 60 for k, v := range scoreMap { fmt.Println(k, v) } }
遍历map时的元素顺序与添加键值对的顺序无关。
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) } }
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]) } }
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) } }
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)
高颜值后台管理系统无偿使用 ### 子枫后台管理系统 ###,可在宝塔面板直接安装
欢迎关注个人公众号:子枫的奇妙世界,得到独家整理的学习资源和平常干货推送。
若是您对个人其余专题内容感兴趣,直达个人我的博客:www.wangmingchang.com 。