版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/winter_wu_1998/article/details/89048816
GO 命令
- go build
- 只对main包下的文件有效
- 在当前目录下生成可执行文件
- 使用 -o 参数显式指定路径和文件名
- 默认作用范围为当前文件夹,编译单个文件需指定文件名
- go install
- 编译和安装文件
- main包文件安装到bin文件夹(.exe)
- 普通包文件安装到pkg/$GOOS文件夹(.a)
- 编译和安装文件
- go run
- 编译和执行程序,不生成文件
- go get
- 获取远程代码包并安装
- -v 显示过程
- -u 强制用网络更新
基础语法
- 包导入
// 相对路径导入 该文件同一目录的model模块
import "./model"
// 绝对路径导入 $GOPATH/pkg/$GOOS/url/model
import "url/model"
import (
f "fmt"
. "http"
_ “sql" // 只想使用包中的init函数
)
-
变量
:=
赋值只能在函数内部,全局变量采用var n int = 1
的方式:=
为初始化,只能对于同名变量出现一次,=为修改,可以出现多次- 交换值:
a, b = b, a
- 大写开头的变量名能被包外引用
-
字符串不可变,
string[0] = 'a'
编译错误 -
别名:
type Color int
type f func(a int) string
-
++只能作为后缀,且不可赋值
a = b++
语法错误
-
iota枚举
- 自动从0开始累积
var( RED Color = iota //0 BLUE // 1 GREEN //2 )
-
初始化
// 数组 a := [...]int{1,2,3} var a [3]int // 切片 var slice []int slice := []int{1,2,3} slice := a[0:2] // 注意此时slice是一个切片类型 slice := make([]int, 10) // 此时一个切片指针 // 字典 var nums map[string]int nums := make(map[string]int) rate := map[stirng]float64{"a":4.5, "bbc":3.0} // 结构体 p := person{"Tom", 35} p:= person{age:35, name:"Tom"} p := new(person) // channel ch := make(chan int) s := make(chan string, 1) var ch chan float64
-
make一般只用于初始化map, slice, channel
-
条件判断(if, switch)
if x > 10 {
...
}
// 初始化并判断
// 此时变量的作用域仅在判断块内
if val, ok := func(); ok {
...
}
// switch无需break,通过fallthrough执行后面的case
switch i {
case 1:
...
fallthrought
case 2:
...
}
- 循环(for)
for i := 0; i < 10; i++{
...
}
for i >= 0 {
i--
...
}
for k,v := range map{
...
}
// 无限循环
for {
...
}
-
函数
// 如果显式指定返回值名,则不用写在return后 // 此时单值也要加括号 func Max(a, b int) (c int) { if (a > b) { c = a } else { c = b } return } // 变参函数 func cout(arg ...string) { for index, val := range arg { ... } } cout("qwe", "asd", "zxc") // 使用slice作为实参时 cout(slice...)
-
defer
- 函数return后执行
- 多个defer逆序执行
-
channel, slice, map本身就是引用类型,传参时不用变为指针
字符串
// 字符串->byte切片
c := []byte(str)
// 字符串排序
s := “14325”
c := strings.Splite(s, "")
sort.Strings(c)
s = strings.Join(c, "")
- strings包包含常用字符串函数
- strconv包包含字符串和别的类型转换的函数
方法
func (s *Struct1)funcName(a,b int) (string,int) {
...
}
- 方法不仅可以作用于自定义的struct上还可以作用域任意类型(int, string等)
- 但要内置类型要起一个别名
- 如果想要改变对象,方法应该作用于指针而不是对象本身
- 可以把recevier当做方法的第一个参数
- 匿名字段
- 结构体中只有类型名而没有变量名的字段
- 于是该结构体继承了内嵌的匿名字段的内部字段和方法
- 以此可以模拟C++中的继承
接口
-
通过接口可以实现泛型和多态
-
空接口可以被任意类型实现
type empty interface{}
-
fmt.Println()****函数就是接受一个实现了String() **方法的接口
-
类型断言
// 判断某一接口变量否是某一类型 // value的类型为实际类型 type Element interface{} var element Element if value,ok := element.(int); ok { ... } else if value, ok := element.(string); ok{ .... } // 上面的写法太麻烦了,可以使用switch-type switch value := element.(type) { case string: ... case int: ... } // 判断某一变量的类型是否实现了某一接口 // val 是一个被某一类型附了值的接口类型变量 var empty Empty if sv, ok = val.(empty); ok { ... }
-
当结构变量作为函数形参时,储存的实际参数不可寻址
- 所以当实际参数是用指针实现接口方法时,如果我们传入是一个实参变量而不是指针,就无法调用指针方法
panic和recover
反射
并发
-
goroutine
- 协程由线程组成,在每个线程上进行多路复用
- 因此比线程更高效和轻量
- 协程不保证执行顺序
-
channel
- 无缓存的协程是柱塞式的,必须等待两边都准备好才开始传递数据,否则休眠
- 有缓存的协程只有当缓冲区写满时才休眠
// 收 val, ok := <-ch // 发 ch <-5 // 关闭通道(一般在函数返回时) // 只有发送方可以关闭 defer close(ch) if v, ok := <- ch; ok { } // for-range可以自动检测通道的关闭 for i:= range ch { ... } // 单向通道 var send chan<- int var recv <-chan int
-
select监听channel
- select默认阻塞,只有监听的channel中有发送或者接受数据时才允许
- 如果设置default则不阻塞,默认执行default
- 多个channel准备好时,随机选一个执行
select{ case <-ch1: ... case <-ch2: ... }