hello GO
这里应用vscode
- 装置插件go
新建hello文件夹,创立main.go文件
package mainimport "fmt"func main(){ fmt.Println("Hello")}
- 关上命令行
- 关上命令行
- 执行go build 这时同目录会创立一个hello.exe的文件(我这里应用的是win电脑)
也能够应用 go build -o aaa.exe 指定文件名
也间接输入可应用 go run main.go
跨平台编译
只须要指定指标操作系统的平台和处理器架构即可:
SET CGO_ENABLED=0 // 禁用CGOSET GOOS=linux // 指标平台是linuxSET GOARCH=amd64 // 指标处理器架构是amd64
而后再执行go build
命令,失去的就是可能在Linux平台运行的可执行文件了。
Mac 下编译 Linux 和 Windows平台 64位 可执行程序:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go buildCGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build
Linux 下编译 Mac 和 Windows 平台64位可执行程序:
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go buildCGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build
Windows下编译Mac平台64位可执行程序:
SET CGO_ENABLED=0SET GOOS=darwinSET GOARCH=amd64go 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 stringvar age intvar iss bool批量申明var ( a string b int c bool)
变量初始化: var 变量名 类型 = 表达式
var name string = "aa"一次初始化多个变量var name,age = "bb",20
短变量申明(申明并初始化) :=
n:=10m:=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
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 mainimport ( "fmt" "math")func main() { fmt.Printf("%f\n", math.Pi) fmt.Printf("%.2f\n", math.Pi)}
复数
complex64和complex128
复数有实部和虚部,complex64的实部和虚部为32位,complex128的实部和虚部为64位。
var c1 complex64c1 = 1 + 2ivar c2 complex128c2 = 2 + 3ifmt.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<<b”是把a的各二进位全副左移b位,高位抛弃,低位补0。 >> 右移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("...") }}输入:ab
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)) //2fmt.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]}
map
map定义
map[KeyType]ValueTypeKeyType:示意键的类型。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]100type of a:map[string]intmap也反对在申明的时候填充元素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)
高颜值后盾管理系统收费应用 ### 子枫后盾管理系统 ###,可在宝塔面板间接装置欢送关注我的公众号:子枫的微妙世界,取得独家整顿的学习资源和日常干货推送。
如果您对我的其余专题内容感兴趣,中转我的集体博客:www.wangmingchang.com 。