非零基础笔记,掌握c的基础上记录
GO mod的使用 1 2 3 4 go mod initgo mod tidy"当然要设置好代言" "https://goproxy.io"
基本 1 2 3 4 5 6 7 8 9 10 11 package main import "fmt" //import了就必须使用 // 不用写; func main(){ //这个括号不能换行 a := 10 //:=是自动识别类型的 b,c := 20,30 var b int //var 变量名 类型 fmt.Println() //自动换行 fmt.Printf() //格式化输出,同c }
匿名变量 1 i,_ := 10,20 // _表示匿名变量 配合函数返回值才有优势 多返回值+占位
常量 1 2 const a int = 10 aonst b = 20 // 没有:= ,也自动推到类型
多个变量或常量到定义 1 2 3 4 5 6 7 8 9 var( a int b float64 ) const( a int = 1 b float64 =1.2 //或者直接=让它自动推到类型 )
iota枚举 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 const( a = iota b = iota c = iota ) 1.iota常量自动生成器,每一行自动加一 2.iota给常量赋值 3iota遇到新的const时重置为0 4.可只写一个iota const ( a = iota b c ) 5.如果同一行,值都一样 const( i = iota j1,j2,j3 = iota,iota,iota //一样 k = iota )
类型别名 1 2 type i int //给int取个别名i ^
if特性 1 2 3 4 //支持初始化 if a:=0;a<10{ ^ ^ 分号隔开 }
switch-case-fallthrough ^跳出,相当于break 支持一个初始化语句,
range迭代 1 2 3 4 str:="abd" for i,data := range str{ //第一期是位置str[],第二个是值 }
函数 1 2 3 4 5 6 7 8 9 10 11 12 13 func 函数名(a int,b string参数列表)(a1 type1,a2 type2返回类型){ 函数体 return v1,v2 } //不定参数列表 func funcName(a ...int){ ...int^不定参数类型,必须放在最后 像一个列表 可以for i,data :=range a{ } }
返回值 1 2 3 4 5 //常用写法 func name()(res int){ res = 666 return //有返回值必须返回嘛,所在go中可以这样写 }
函数也是一种数据类型 1 2 3 4 5 6 7 8 9 10 11 12 13 //故可以用type重命名 type newname func(a,b int) int{ } var a newname a = (1,2) //回调函数,例 func cala(a,b int, fuc newname) int { fuc(a, b) } // ^多态了 func main(){ cala(1,2,add) }
###匿名函数
1 2 3 4 5 6 7 8 f1 := func(){ //没有参数,闭包可捕获到外层到变量,影响到外面 //不管变量到作用域,只要闭包还在使用他,变量就还在 } //匿名函数定义了就要有东西来接 //不然这么写 func(){ }() ^这个括号表示传进去到参数,然后直接调用
###defer
1 2 3 4 1.延迟调用,函数结束前(那一刻)调用 2.先写到后调用 3.多个defer调用时,哪怕其中有个出了错,其他仍然会执行 4.相当于先按顺序读,然后默默记住,再倒序输出
###获取命令行参数
1 2 3 4 5 6 1.导入包 import "os" 2.接收传入的参数 //全都是以字符串形式 str := os.Args <这个表示 tips:可用不定参数接,可用range迭代接
###导入包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 同一个目录包名必须一样 同一个目录调用别的文件的函数无需包名 不同目录包名不一样 调用的别的包的函数首字母必须大写 1.除传统写法还可 import( "" "" ) 2.起别名 import 别名 "fmt" 3. .操作 import . "fmt" //调用函数无需通过包名 4.忽略次包名 import _ "fmt" 这个操作时为了调用包中的init函数
###init函数
1 2 3 4 5 导入一个包就先执行一个包的init函数 func init(){ } 所以 import _ "" 操作的目的时调用init函数而不用其他函数
数组 1 2 3 4 5 6 7 8 9 10 11 12 13 //指定下标初始化 d := [5]int{2: 10,4: 2} ^指定的下标 //数组比较 比较类型和每个元素 //同类型的数组可以赋值 //数组做函数参数->拷贝,值传递 //数组指针防止值传递^ p *[7]int (*p)[0] <-注意写法
随机数的使用 1 2 1. import 2. 设置种子 //种子参数一样产生的随机数一样
切片 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 array := [...]int{10, 20, 30, 0, 0} slice := array[low:high:max] //切片 low->起点 high->终点 //不包括 长度=high - low 容量=max - low //意义不明 创建方式: 1.传统方式 s1 := []int{1,2,3} //自动推到类型同时初始化 2.make函数 s2 := make([]int, len, cap) ^切片类型 ^默认不写和len一样 切片操作 类似python 操作某个元素和数组操作一样 append函数,向后追加,自动以两倍容量扩容 copy函数,copy(目标切片, 原切切片) !!!切片做函数参数!!! 引用传递,会影响到外面
切片和数组的区别&&关系 1 2 3 4 5 数组长度固定,切片[]里面为空或...长度可以不固定 a := [7]int{} s := []int{} <- 切片 对切片操作会影响到底层数组
map 1 2 3 4 5 6 7 格式: map[keyType]valueType 创建方式 1. var m1 map[int]string 2. m2 := make(map[int]string) 3. m2 := make(map[int]string, len) //指定容量,自动扩容,提前分配提高效率
int和string的转换 1 2 3 4 5 6 7 8 9 10 #string到int int,err:=strconv.Atoi(string) #string到int64 int64, err := strconv.ParseInt(string, 10, 64) #int到string string:=strconv.Itoa(int) #int64到string string:=strconv.FormatInt(int64,10) 同类型之间转换,比如int64到int,直接int(int64)即可;
接收复杂的类型一般自定义结构体 1 2 因为http只能传字符串,所以前端要传json的话要先把json转换成json字符串 ……
高并发 goroutine go func{}
以并发形式执行而不需等待执行完成
当一个goroutine尝试在一个channel上发送(ch<- expression
)或接收(<-ch
)时,这个goroutine会阻塞在调用处,直到另一个goroutine从这个channel中接受或发送。
箭头符:<- goroutine是golang中在语言级别实现的轻量级线程,仅仅利用 go 就能立刻起一个新线程。多线程会引入线程之间的同步问题,在golang中可以使用channel作为同步的工具。
通过channel可以实现两个goroutine之间的通信。
创建一个channel, make(chan TYPE {, NUM})
, TYPE指的是channel中传输的数据类型,第二个参数是可选的,指的是channel的容量大小。
向channel传入数据, CHAN <- DATA
, CHAN 指的是目的channel即收集数据的一方, DATA 则是要传的数据。
从channel读取数据, DATA := <-CHAN
,和向channel传入数据相反,在数据输送箭头的右侧的是channel,形象地展现了数据从‘隧道’流出到变量里。
杂项 参数绑定 以gin框架为例
1 2 3 4 5 type Person struct { Name string `json:"name" form:"name" binding:required` Age int `json:"age" form:"age"` Address string `json:"address" form:"addr"` }
``
之间的标记表明了了映射关系和数据来源,这样使用gin的bind
函数就可生成Person实例。json
标记表明了映射成json时使用的名称如name,而不是Name,或使用json中的对应字段完成映射。form
标记表明了从表单中获取映射。required
标记表明了必须要有这个参数,没有会报错。当然binding等标记还有其他用法,和自定义,详见官方文档。
gin的这个binding功能使用了第三方的验证器,validator。