定义: const
iota 在const 出现时将会垂直为0,
package mainimport ( "fmt")//常量定义// 在程序运行期间不能修改,const ( code=200)// 批量声明常量,如果某一行没有赋值, 默认和上面一行一致const( m1=100 m2=200 m3)// iota 类似于枚举const( n1=iota //0 n2 _ n3)const( d1,d2=iota+1, iota+2 d3,d4=iota+3,iota+4)// 定义数据量级const( _=iota KB = 1 << (10 * iota) MB = 1 << (10 * iota) GB = 1 << (10 * iota) TB = 1 << (10 * iota) PB = 1 << (10 * iota))func main() { fmt.Println("KB",KB) fmt.Println("MB",MB) fmt.Println("GB",GB) fmt.Println("TB",TB) fmt.Println("PB",PB)}
分支控制
package mainimport ( "fmt")func main() { //流程控制 var n int =80 if n>100 { fmt.Printf("大家好%#v\n",n) }else if n==100 { fmt.Println("小盆友好。。。。。",n) }else if n==90{ fmt.Println("========正常人") }else { fmt.Println("=============") } }
特殊写法
package mainimport ( "fmt")func main() { //流程控制 // n的作用域在 if中 if n:=80; n>100 { fmt.Printf("大家好%#v\n",n) }else if n==100 { fmt.Println("小盆友好。。。。。",n) }else { fmt.Println("=============") } fmt.Println("n",n)}
for 循环
for 初始化语句;条件表达式;累加语句
package mainimport ( "fmt")func main() { //for 循环 for i:=0; i<10 ; i++{ fmt.Println("i",i) } // var i int=5 for ; i<10;i++{ fmt.Println("i",i) } // 结束语句可以 for ; i<10 ;{ fmt.Println("i",i) i++ } //死循环// for {// fmt.Println("=====",i)// } //for range (键值循环) s:="小米,你好" for i, v :=range s{ fmt.Printf("%d %c\n",i,v) } }
for 跳从循环
package mainimport ( "fmt")func main() { //for 循环 跳出for循环 // 一、使用break // 跳过for 循环 continue for i:=0; i<10 ; i++{ if i==5{ break } fmt.Println("i",i) } fmt.Println("over=========") for i:=0; i<10 ; i++{ if i==5{ continue } fmt.Println("i",i) } fmt.Println("over")}
switch
package mainimport ( "fmt")func main() { //switch 循环 var n int=6 switch(n){ case 1: fmt.Println("=====1======") case 2: fmt.Println("=====2======") case 3: fmt.Println("=====3======") case 4: fmt.Println("=====4======") case 5: fmt.Println("=====5=====") default: fmt.Println("===========") }}
package mainimport ( "fmt")func main() { //switch 循环 switch n:=7;n{ case 1,2,3,4: fmt.Println("=====1======") case 5: fmt.Println("=====5=====") default: fmt.Println("===========") }}
package mainimport ( "fmt")func main() { //switch 循环 n:=10 switch { case n>10: fmt.Println("=====1======") case n<=10: fmt.Println("=====5=====",n) }}
fallthrough 语句 向下穿一个
数组
数组长度和 类型是 数组一部分
package main
import (
"fmt"
)
func main() {
//复合数据类型
//数组
// 存放元素的容器
// 必须指定存放的元素类型和容量
var a1 [3] bool
fmt.Printf("a1:%T",a1)
//初始化
//如果不初始化,默认元素是默认值 布尔类型
// 1、初始化
a1 =[3]bool{true,true,true}
fmt.Println("a1",a1)
//2、初始化2
// 初始化的值自动推断元素的值
a4:=[...]int{0,2,3,4}
fmt.Println("a4", a4)
//3、初始化
//根据索引来初始化 数组
a3:=[5]int{0:1,4:2}
fmt.Println("a3",a3)
}
package main
import (
"fmt"
)
func main() {
//复合数据类型
//数组
// 存放元素的容器
// 必须指定存放的元素类型和容量
var a1 [3] bool
fmt.Printf("a1:%T",a1)
//初始化
//如果不初始化,默认元素是默认值 布尔类型
// 1、初始化
a1 =[3]bool{true,true,true}
fmt.Println("a1",a1)
//2、初始化2
// 初始化的值自动推断元素的值
a4:=[...]int{0,2,3,4}
fmt.Println("a4", a4)
//3、初始化
//根据索引来初始化 数组
a3:=[5]int{0:1,4:2}
fmt.Println("a3",a3)
//数组for 循环
//1、根据索引遍历
for i:=0;i<len(a4);i++{
fmt.Println(a4[i])
}
// 2、 for range 遍历
for i, v := range a4 {
fmt.Println(i,v)
}
// 多维数组
var n1 [3][2] int
n1=[3][2]int{
{1,2},
{2,3},
{3,4},
}
fmt.Println(n1)
}
数组支持 等于 不等于操作
切片
package main
import (
"fmt"
)
func main() {
//复合数据类型
//切片
var s1 [] int
var s2 [] string
fmt.Println(s1,s2)
// nil 判断是不是空
// nil 没有开辟内存空间
fmt.Println(s1==nil,s2==nil)
//初始化
s1 =[]int{1,2,3}
s2=[]string{"北京","上海"}
fmt.Println(s1,s2)
//长度和容量
fmt.Println("len",len(s1),len(s2),"cap",cap(s1),cap(s2))
//由数组得到 切片
a1 :=[2]int{1,2}
// 左包含 右不包含 左闭右开
a2 :=a1[0:1]
fmt.Println("a1",a2,cap(a2))
a3 :=a2[:]
fmt.Printf("%T",a3)
}
make 函数构造切片
切片的本质是一个框,框住了一块连续的内存, 是一个引用类型,底层数据保存在数组中。
切片不能直接比较 是引用类型 当一个切片nil 底层是没有数组 一个nil 的长度和容量都是0 但我们不能认为一个长度和容量都是0的切片一定是nil
判断一个切片是不是空的 一定是len()==0 来判断 不能使用s==nil
package main
import (
"fmt"
)
func main() {
//复合数据类型
// make 函数 创建切片
// make(类型,长度,容量)
// 容量 不填默认和长度一致
s1 := make([]int,5)
s2 := make ([]int16,10)
fmt.Println("s1",s1)
fmt.Println("s2",s2)
// 索引遍历
for i:=0;i<len(s1);i++{
fmt.Println(s1[i])
}
// for range 遍历
for i,v:=range s2{
fmt.Println(i,v)
}
}
切片的append()方法
package main
import (
"fmt"
)
func main() {
//复合数据类型
// append() 为切片追加元素
s1 := []string{"深圳","北京","上海","广州"}
//s1[5]="李四" //索引越界
// 调用append 函数必须用原来的切片变量接收
s1=append(s1,"李四")
// append 追加元素,原来的数组 容量不够, cap 换了一个底层数组队
// 必须使用原来的
fmt.Println(s1,len(s1),cap(s1))
}
package main
import (
"fmt"
)
func main() {
//复合数据类型
// append() 为切片追加元素
s1 := []string{"深圳","北京","上海","广州"}
//s1[5]="李四" //索引越界
// 调用append 函数必须用原来的切片变量接收
s1=append(s1,"李四","小米","小红","小明","雄安")
// append 追加元素,原来的数组 容量不够, cap 换了一个底层数组队
// 必须使用原来的
ss := [] string{"a","d","b"}
s1=append(s1, ss...)
fmt.Println(s1,len(s1),cap(s1))
}
package main
import (
"fmt"
)
func main() {
//复合数据类型
// copy(新切片,需要复制的切片)
s1 := []int{1,2,3}
s2 :=s1
var s4=make([]int,3)
s1[1]=3
// 引用类型
copy(s4,s2)
fmt.Println(s4)
// 从切片中删除元素
m1 := [3]int{1,2,3}
n1 := [] int {1,2,3,4,5,6,7,8,9}
n1=append(n1[0:1],m1[:]...)
// 切片不存值 数据存储在底层数组
n1[1]=7
fmt.Println(n1)
}
package main
import (
"fmt"
)
func main() {
//复合数据类型
var a=make([]int,5,10)
// copy(新切片,需要复制的切片)
fmt.Println(a)
for i := 0; i < 10; i++ {
a=append(a,i)
}
fmt.Println(a)
fmt.Println(cap(a))
}
make 和new的区别
1、make和new 都是用于申请内存的
2、new 一般给基本数据类型申请内存 ,基本数据类型返回对应的指针类型
3、 make一般给slice、map、chan 申请内存,make函数返回的是对应的三个个类型本身
package main
import (
"fmt"
)
func main() {
//复合数据类型
//make [keyType]valueType
var m1 map[int]string
// 估计好内存容量 避免动态扩容
m1=make(map[int]string,10)
m1[1]="小米"
m1[2]="红米"
// 接收map的值
v,ok:=m1[3]
if !ok{
fmt.Println(v,"ssss")
}else {
fmt.Println(v)
}
}
package main
import (
"fmt"
)
func main() {
//复合数据类型
//make [keyType]valueType
var m1 map[int]string
// 估计好内存容量 避免动态扩容
m1=make(map[int]string,10)
m1[1]="小米"
m1[2]="红米"
// 接收map的值
for k, v := range m1 {
fmt.Println(k,v)
}
// 只遍历 k
for k:=range m1 {
fmt.Println(k)
}
//只遍历 v
for _,v:=range m1 {
fmt.Println(v)
}
//删除
delete(m1,2)
//
delete(m1,3)
fmt.Println(m1)
}
函数
package main
import (
"fmt"
)
// 函数定义
// func 函数名(参数名)(返回参数){
//函数体
//}
func main() {
sum := sum(1,2,3)
fmt.Println(sum)
}
// 有参数 有返回值
// 返回值 可以命名 可以不命名
// 不命名 显式返回
// 命名 不需要 return 返回值 return 不能省略
func sum(x int, y ...int)(ret int){
ret=x+y[0]
return
}
// 有参数 没有返回值
func sumx(){
fmt.Println("大家好。。。。")
}
//多个 返回值
// 参数的类型 简写 两个参数的类型一致 前面的类型简写
// 可变长参数放最后
func sumy(x,y int) int{
return x+y
}
// go 没有默认参数
package main
import (
"fmt"
)
// 函数定义
func main() {
sum:=sum(1,2,3,4,5,6,7)
fmt.Println(sum)
}
// 命名函数不能 再命名命名函数
func sum (x int ,y ...int)(sum int) {
sum=x
for v:= range y {
sum+=y[v]
}
return sum
}
defer 机制
defer 从后到前执行
package main
import (
"fmt"
)
// 函数定义
func main() {
sum:=sum(1,2,3,4,5,6,7)
fmt.Println(sum)
}
// 命名函数不能 再命名命名函数
func sum (x int ,y ...int)(sum int) {
sum=x
for v:= range y {
sum+=y[v]
}
defer fmt.Println("我执行了。。。。。。")
defer fmt.Println("。。。。。。。")
return sum
}
匿名函数
package main
import (
"fmt"
)
// 函数定义
func main() {
sum:=sum(1,2,3,4,5,6,7)
fmt.Println(sum)
}
// 命名函数不能 再命名命名函数
func sum (x int ,y ...int)(sum int) {
sum=x
for v:= range y {
sum+=y[v]
}
fmt.Println(sum)
// 返回函数 函数从上到下
// 匿名函数
// func (参数列表)(返回值列表){
// 函数体
// }(函数调用)
//
defer func() {
fmt.Println("dddddd")
sum+=1
}()
return sum
}
全局作用域
package main
import (
"fmt"
)
var age int=18
// 函数类型以及变量
// 函数也可以作为参数类型传入
// 函数也是类型
func main() {
// 函数也是类型
m2:=sum(su)
fmt.Println(m2)
}
func sum(x func() int)int {
age=20
return x()+3
}
func su() int{
return 2
}
变量作用域
1、全局作用域
2、函数作用域
1、先在函数内部找变量,找不到再去全局找
2、函数内部的变量,外部访问不到
3、代码块作用域
package main
import (
"fmt"
)
var age int=18
// 函数类型以及变量
// 函数也可以作为参数类型传入
// 函数也是类型
func main() {
// 函数也是类型
m2:=sort(3)
s()
fmt.Println(m2)
}
func sort(x int) int {
if x==1{
return x
}
// 立即执行函数
// 如果只是调用一次的函数 立即执行函数
func (){
fmt.Println("大家好。。。。。")
}()
return sort(x-1)*x
}
// 匿名函数 写在函数内部
var s=func(){
fmt.Println("dddd")
}
闭包
闭包是一个函数 能包含外部作用域的变量
package main
import (
"fmt"
)
var age int=18
// 闭包
// 闭包是一个函数 能包含外部作用域的变量
// 底层原理
// 1、函数作为返回值
// 2、函数内部查找变量的顺序,先在自己函数内部找 再从外部找
func f1(f func()){
fmt.Println("this is f1")
f()
}
// 闭包
func f2(y int)func(x int) int{
return func(x int) int {
return x+y
}
}
func main(){
var req= f2(2)(3)
fmt.Printf("%T",req)
}
panic /recover
package main
import (
"fmt"
)
var age int=18
// 闭包
// panic /recover 当程序出现错误
func funcA(){
fmt.Println("A")
}
func funcB(){
defer func(){
fmt.Println("ccccccc")
recover()
}()
panic("出现错误了。。。") //程序崩溃退出
fmt.Println("B") //不执行。。
}
func funcC(){
fmt.Println("C")
}
func main(){
funcA()
funcB()
funcC()
}
fmt包的
print函数
%T
%t bool类型
%d 十进制
%b 二进制
%x
%0 八进制
%c 字符
%s 字符串
%f 浮点数
%v 值
结构体
自定义类型:
package main
import (
"fmt"
)
// 自定义类型 和类型别名
// type 后面的类型
type myInt int
// 类型别名
// 编写中存在 编译后不存在
// rune
type youInt=int
func main(){
var n myInt=1000
var m youInt=100
var c rune
c='总'
fmt.Printf("%T\n",n)
fmt.Printf("%T\n",m)
fmt.Printf("%T",c)
}
package main
import (
"fmt"
)
// 自定义类型 和类型别名
// type 后面的类型
type person struct{
name string
age int
gender string
address string
}
func main(){
var p person
p.name="小米"
p.age=18
p.address="北京"
p.gender="2022-12-20"
fmt.Println(p)
fmt.Println(p.name)
}
创建指针类型的结构体
package main
import (
"fmt"
)
type person struct{
name string
age int
}
// 函数传参 永远是副本
func f1(x person){
x.age=20
}
// 修改值
// 修改内存地址
func f2(x *person){
(*x).age=20
}
// 匿名结构体
func main(){
var p person
p.age=100
p.name="小明"
f1(p)
f2(&p)
fmt.Println(p)
}
方法
package main
import (
"fmt"
)
type person struct{
name string
age int
}
// 结构体构造函数
// 返回的是结构体还是结构体指针
// 当结构体比较大时 考虑使用结构体指针
func newPerson(name string,age int) *person{
return &person{
name: name,
age: age,
}
}
// 方法限定接收者
// func 方法接收者 方法名(参数)返回值{
// 方法体
//}
func (p person)setName(){
fmt.Println("大家好。。。。",p.name)
}
// 匿名结构体
func main(){
p1:=newPerson("小米",18)
p2:=newPerson("小红",20)
p1.setName()
fmt.Println(*p1,*p2)
}
结构体匿名字
默认把类型当成名字
package main
import (
"fmt"
)
type person struct{
string
int
}
// 结构体构造函数
// 返回的是结构体还是结构体指针
// 当结构体比较大时 考虑使用结构体指针
func newPerson(name string,age int) *person{
return &person{
string : name,
int : age,
}
}
// 方法限定接收者
// func 方法接收者 方法名(参数)返回值{
// 方法体
//}
func (p person)setName(){
fmt.Println("大家好。。。。",p.string)
}
// 匿名结构体
func main(){
p1:=newPerson("小米",18)
p2:=newPerson("小红",20)
p1.setName()
fmt.Println(*p1,*p2)
}
package main
import (
"fmt"
)
// 结构体嵌套
type person struct{
name string
age int
addr address
}
type address struct{
city string
province string
}
func main(){
p1:= person{
name: "xiaomi",
age: 18,
addr: address{
province: "山东",
city:"实施",
},
}
fmt.Println(p1)
}
匿名嵌套
package main
import (
"fmt"
)
// 结构体嵌套
type person struct{
name string
age int
address
}
type address struct{
city string
province string
}
func main(){
p1:= person{
name: "xiaomi",
age: 18,
address:address{
province: "山东",
city:"实施",
},
}
fmt.Println(p1.city)
}
《JSON》
package main
import (
"encoding/json"
"fmt"
)
// 结构体转换为json 的字符串
type anlmal struct{
Name string `json:"name"`
Age int `json:"age"`
}
// 序列化
func main(){
n1:=anlmal{
Name: "xiaomi",
Age: 18,
}
b,_:=json.Marshal(n1)
fmt.Println(string(b))
//反序列化
str :=`{"name":"xiaomi","age":18}`
var a anlmal
json.Unmarshal([]byte(str),&a)
fmt.Println(a)
}
时间和 日期相关函数
package main
import (
"fmt"
"time"
)
// 结构体转换为json 的字符串
type anlmal struct {
Name string `json:"name"`
Age int `json:"age"`
}
//
func main() {
var tim=time.Now()
fmt.Println(tim)
var Year=tim.Year()
var Month=int(tim.Month())
var day=tim.Day()
fmt.Println(Year,Month,day)
fmt.Print(tim.Format("2006-01-02 15:04:05"))
}
2006-01-02 15:04:05 数值是固定的
时间常量
package main
import (
"fmt"
"time"
)
// 结构体转换为json 的字符串
type anlmal struct {
Name string `json:"name"`
Age int `json:"age"`
}
// 时间常量
const(
)
func main() {
var tim=time.Now()
for i:=0;i<100;i++{
fmt.Println(i)
time.Sleep(time.Second)
if(i<100){
break
}
}
//Unix 和 UnixNano
fmt.Println(tim.Unix(),tim.UnixNano())
}
单元测试
goroutine
package main
import (
"fmt"
"strconv"
"time"
)
//gorotine
func main() {
//开启协程
go test()
for i:=0;i<10;i++{
fmt.Println("Hello,word==主线程===="+strconv.Itoa(i))
time.Sleep(time.Second)
}
}
func test(){
for i:=0;i<10;i++{
fmt.Println("Hello,word"+strconv.Itoa(i))
time.Sleep(time.Second)
}
}
MPG模式基本介绍
1、M 操作系统的主线程(是物理线程)
2、P:协程执行需要的上下文
3、G:协程
package main
import (
"fmt"
"runtime"
)
//gorotine
func main() {
//开启协程
num:=runtime.NumCPU()
fmt.Println("CPU",num)
//可以设置使用多个CPU
runtime.SetCPUProfileRate(num-1)
fmt.Println("ok")
}
共享资源竞争
package main
import (
"fmt"
"time"
)
var (
mymap =make(map[int]int)
)
//gorotine
func main() {
//开启协程
for i:=1; i<200;i++{
go test(i)
}
//遍历结果
time.Sleep(1000*time.Second)
for i,v:=range mymap {
fmt.Println(i,v)
}
}
func test(n int){
res:=1
for i := 0; i <=n; i++ {
res*=i
}
mymap[n]=res
}
package main
import (
"fmt"
"sync"
"time"
_ "time"
)
var (
mymap =make(map[int]int , 10)
lock sync.Mutex
)
//gorotine
func main() {
//开启协程
for i:=1; i<70;i++{
go test(i)
}
//遍历结果
time.Sleep(8*time.Second)
lock.Lock()
for i,v:=range mymap {
fmt.Println(i,v)
}
lock.Unlock()
}
func test(n int){
res:=1
for i := 1; i <=n; i++ {
res*=i
}
// 加锁
lock.Lock()
mymap[n]=res
//解锁
defer lock.Unlock()
}
channel(管道)
队列: 先进先出
channel 引用类型
package main
import (
"fmt"
)
//channel
func main() {
var intChan chan int
intChan=make(chan int,2)
//向管道写数据
intChan <- 10
num:=100
intChan<-num
// 向管道写入数据时,不能超过其容量
// all goroutines are asleep - deadlock!
//intChan <-10
//查看管道的长度和容量
//容量不会自动增长
fmt.Println(len(intChan),cap(intChan))
//5.从管道中取数据出来
num2:=<-intChan
fmt.Println(num2)
fmt.Println(len(intChan),cap(intChan))
// 没有使用协程 如果没有数据了,会报错
num3:=<-intChan
//all goroutines are asleep - deadlock!
num4:=<-intChan
fmt.Println(num3,num4)
}
注意事项
package main
import (
"fmt"
)
type cat struct{
name string
age int
}
//channel
func main() {
intChan:=make( chan interface{},10)
cat1:=cat{
name: "tome",
age:18,
}
cat2 := cat{
name: "tome",
age: 180,
}
intChan <- cat1
intChan <- cat2
intChan <- "李四"
intChan <- 10
num :=<- intChan
numz:=num.(cat)
fmt.Printf("%T\n",num)
fmt.Printf("%v\n",numz.name)
num3 :=<- intChan
numx:=num3.(cat)
fmt.Println(numx.age)
}
channel遍历
package main
import (
"fmt"
)
type cat struct{
name string
age int
}
//channel
func main() {
intchan :=make(chan interface{},10)
num :=10
intchan <- num
intchan <- 10
intchan <- 20
intchan <- 30
intchan <- 40
intchan <- 50
intchan <- 60
intchan <- 100
// close 专门关闭函数的
close(intchan)
for v := range intchan {
fmt.Println(v)
}
}
package main
import (
"fmt"
)
//channel 只读或者只写
func main() {
//读写
intChen:=make(chan int,20)
intChen<- 10
// 声明只读
var chan2 chan<- int
chan2=make(chan int,10)
chan2 <-10
num :=<- chan2
defer close(intChen)
defer close(chan2)
fmt.Println("大家好。。。。")
}
select
package main
import (
"fmt"
)
//channel 只读或者只写
func main() {
//读写
intChen:=make(chan int,20)
for i:=1;i<=10;i++{
intChen <- i
}
//
stringChan :=make(chan string,20)
for i:=1; i<=5;i++{
stringChan <- "hello"+ fmt.Sprintf("%d",i)
}
//channel 管道不关闭 没有数据 会
sdd: for {
select {
// 会自动匹配下一个 case
case v:= <- intChen:
fmt.Println("从intcha读取数据。。。",v)
case v:= <- stringChan:
fmt.Println("从stringChan读取数据。。。",v)
default:
fmt.Println("读取不到数据。。。")
break sdd
// return 结束程序
}
}
}
package main
import (
"fmt"
"time"
)
//channel 只读或者只写
// 协程发生异常
// defer + recover
func main() {
go sayHello()
go test()
for i:=0; i<10 ;i++{
fmt.Println("Hello WORD")
}
}
func sayHello(){
for i:=0;i<10 ;i++{
time.Sleep(time.Second)
fmt.Println("hello word")
}
}
func test(){
var myMap map[int]string
defer func () {
if err:=recover(); err !=nil{
fmt.Println("发生异常了",err)
}
}()
myMap[0]="golang"
}
反射