如何你使用的是Chrome,可以试试Ctrl+F搜索你想要找的内容!
会持续更新的。
package main //声明代码在哪个包里面,就是位置在哪
import "fmt" //引用依赖库,fmt是标准库
func main(){} //功能函数
os.Exit(-1) //main函数不支持返回值,使用这个代码返回
fmt.Println() //输出打印
os.Args //获得命令行参数
编写测试程序的源码文件以 _test 结尾:xxx_test.go
测试方法名以 Test 开头:func TestXXX(t *testing.T){}
多个文件共用的函数首字母大写:func Xxxx(){}
import "testing" //引用依赖库,testing是测试库
func TestFirstTry(t *testing.T) {
t.Log("My first try!") //打印测试结果
}
var a int =1 //定义变量
var (
a int =1
b int =1
) //定义变量
a:=1 //使用类型推断定义变量
a,b=b,a //支持互换
const( //常量定义
mon=iots //常量计数器,初始值为0,每一个const内都是0开始
tues //1
wedn //2
)
const( //常量定义
mon=1 << iota //001,左移
tues //010
wedn //100
)
基本数据类型:
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
byte
rune
float32 float64
complex64 complex128
类型转化:Go语言不允许隐式类型转换,别名也不行,只要类型名不一样就不可以隐式转换
math.MaxInt64 //最大的整型
math.MaxFloat64 //最大的浮点型
math.MaxUint32 //最大的无符号整型
b:=&a //取地址符,Go的指针地址不支持运算
t.Logf("%T",a) //%T是输出类型
nil //空值
var a string //初始化字符串变量,初始化后是空值nil
a++ //不支持前置++,即++a
a:=[...]int{1,2,3} //数组初始化
b:=[...]int{3,4,5}
t.Log(a==b) //false,数组之间可以直接比较
1 &^ 1 //0,按位清零,如果右边为1,那么结果清零,右边是0,那么结果与左边一样
条件和循环
n:=0
for n<5 { //while循环
n++
}
for { //无限循环
n++
}
if ...else...
if ... else if...
if a:=1;a{} //if支持赋值
switch条件:
1.条件表达式不限制为常量或则整数
2.case可以多个结果一起
3.不需要手动break
4.可以与if else方式相同
switch a:=1;a{}//支持常量,字符串,整形,不需要手动添加break
case 0,2://支持两个,只要命中一个就行
fmt.Println("0,3")
switch{
case 0<=num && num<=3:
fmt.Println("0-3")
case 3<=num && num<=6:
fmt.Println("3-6")
} //和if else相同,看起来很方便
数组
var arr [3]int //声明并初始化为默认零值
arr[0] == 1
b:= [3]int{1,2,3} //声明同时初始化
c:= [2][2]int{{1,2},{2,3}} //多维数组初始化
for idx,e:=range arr {
t.Log(idx,e)
} //循环输出数组,range是关键字,idx是索引,e是值,idx可以换成_,代表不关心索引
arr[1:2] //arr[1],数组的截取
arr[:2]
arr[1:]
切片
var s0 []int
s0 = append(s0,1) //为数组增加一个值为1,len一个一个增加,而cap是*2的增加,append是如果超出了cap,那么就需要新使用一个连续存储空间,所以需要使用=赋值
t.Log(len(s0),cap(s0)) //输出长度和空间
s1:=make([]int ,3, 5) //初始化一个长度为3,空间为5的数组
{
a:= []int{1,2,3,4,5,6,7,8}
b:= a[2:4]
t.Log(b,len(b),cap(b)) //[3,4],2,6,可以发现这个cap是从这个位置一直到最开始a那个数组的结束,相当于b是切片的a[2]这个位置的指针,此时a与b共享存储空间,所有数组切片的地址空间是没有变化的
}
数组与切片的不同:数组可以比较,切片不可以比较,切片可以伸缩,数组不可以
a:=[...]int{1,2,3,4} //数组
b:=[]int{1,2,3,4} //切片
Map声明
m:=map[string]int{"one":1,"two",2}
m1:=map[string]int{}
m1["one"]=1
m2:=make(map[string]int,10)
if c,ok:=m[3];ok{} //判断是否存在,不存在nil,通常赋值0,所以使用这种方式判断是否存在
for k,v:=range m{} //Map遍历
m:=map[int]func(op int)int{} //Map的value可以是方法
m[1]=func(op int) int{return 0}
mySet:=map[int]bool{} //创建一个Set集合
字符串
1.string是数据类型,不是引用或者指针
2.是只读的、不可变的byte切片,len可以统一它的byte数
3.可以存放任何数据
Unicode是一种字符集
UTF8是unicode的存储实现,物理存储
s="中" // \xE4\xB8\xAD 是三个byte
t.Log(len(s)) //3
c:=[]rune(s) //表示unicode编码的值int 的值
t.Log(len(c)) //1
t.Log("unicode %x",c[0]) //4e2d
t.Log("utf8 %x",s) //e4b8ad,和前面那个二进制一样
常用字符串函数
strings.Split(s,",") //字符串分割
strings.Join(s,"-") //字符串连接
strconv.Itoa(10) //把数字转换成字符串
i,err:=strconv.Atoi("10") //把数字转换成字符串,err表示转换有没有问题
函数:
1.可以返回多个值
2.所有参数都是值传递
3.函数可以作为变量的值
4.函数可以作为参数和返回值
计时函数:
func timeSpent(inner func (op int) int) func (op int) int{
return func(n int) int {
start := time.Now()
ret := inner(n)
fmt.Println("time spent:", time.Since(start).Seconds())
return ret
}
}
可变长参数:
func sum(ops ...int) int{} //ops是数组
延迟运行函数:
defer 在函数执行完之后 return 前才执行
结构体
type Employee struct {
Id string
Name string
Age int
}
e := Employee{"a","b",10} //初始化
e := Employee{Id:"a",Name:"b",Age:10} //初始化
e := new(Employee) //这是一个指针
e.Id="a"
func (e *Employee) String() string{} //为结构体构建方法
接口
type Programmer interface{
WriteHelloWorld() string //定义方法
}
func (e *Employee) WriteHelloWorld() string{} //实现方法
func Dosomethhing(p interface{}){ //空接口
if i,ok := p.(int);ok{} //判断输入进来的是否是整形
}
Go的错误机制
1.没有异常机制
2.error类型实现了error接口
3.可以使用error.New来快速创建错误实例
type error interface{
Error() string
}
errors.New("this is a error")
panic 用于不可以恢复的错误,退出前会执行defer指定内容
panic与os.Exit区别:
1.os.Exit退出时不会调用defer
2.os.Exit退出时不会输出当前的调用栈信息
panic(errors.New("error"))
os. Exit(-1)
defer func{
if err := recover() ;err ! = nil{ //recover错误恢复,可以获取上面那个panic中errors的字符串,然后返回
fmt. Println(err)
}
}
package:通过go get来货的远程依赖,go get -u强制从网络更新远程依赖
go get -u github.com/a/b
import cm "github.com/a/b"
协程:
for i := 0 ;i<10;i++{
go func(i int){ //go 协程
fmt.Println(i)
}(i) //传递了i进去
}
共享内存并发
func TestCounterWaitGroup(t *testing.T){
var mut sync.Mutex
var wg sync.WaitGroup
counter := 0
for i := 0 ;i<5000;i++{
wg.Add(1)
go func(){
defer func(){
mut.Unlock()
}()
mut.Lock()
counter++
wg.Done()
}()
}
wg.Wait()
t.Logf("counter = %d",counter)
}
CSP并发机制:
func service() string {
time.Sleep(time.Millisecond * 50)
return "Done"
}
func otherTask(){
fmt.Println("working on something else")
time.Sleep(time.Millisecond * 100)
fmt.Println("Task is done.")
}
func AsyncService() chan string{
retCh := make(chan string) //声明一个通道
go func() {
ret := service()
fmt.Println("returned result.")
retCh <- ret //传入通道
fmt.Println("service exited.")
}()
return retCh
}
func TestAsyncService(t *testing.T) {
retCh := AsyncService()
otherTask()
fmt.Println(<-retCh) //取出通道内容
time.Sleep(time.Second*1)
}
//输出
//working on something else
//returned result.
//Task is done.
//Done
//service exited.
多路选择:
select {
case ret := <-retCh1
t.Logf("1")
case ret := <-retCh2
t.Logf("2")
default:
t.Error("no one returned")
}
超时控制:
select {
case ret := <-AsyncServise(): //如果没有返回则一直等待
t.Log(ret)
case <-time.After(time.Millisecond *100): //判断超时
t.Error("time out"
}
ch:=make(chan int)
close(ch) //关闭通道
if data,ok := <-ch;ok:{} //通过ok判断通道是否关闭,如果关闭data是ch类型的0值
性能测试
func BenchmarkConcatStringByAdd(b *testing.B){ //性能测试
//与性能无关代码
b.ResetTimer() //重置时间
for i := 0;i<b.N;i++{
//测试代码
}
b.StopTimer() //停止计时
//与性能无关代码
}
var f int64 =10
t.Log(reflect.TypeOf(f),reflect.ValueOf(f),reflect.ValueOf(f).Type()) //int64 10 int64 ,反射编程,获得变量类型和值
a:=map[int]string{1:"one",2:"two"}
b:=map[int]string{1:"one",2:"two"}
t.Log(reflect.DeepEqual(a,b)) //true,总所周知两个数组可以直接比较,但是map和切片是不可以的,这个函数实现了map和切片的比较
reflect.ValueOf(*e).FiledByName("Name") //按名字访问结构的成员
reflect.ValueOf(e).MethodByName("UpdateAge").Call([]reflect.Value{reflect.ValueOf(1)}) //按名字访问结构的方法
type BasicInfo struct {
Name string 'json:"name"' //Struct Tag,结构体标签
}
vstr=vstr.Elem() //获得指针指向的结构
var jsonStr='{"a":{"b":"c"}}' //json字符串
e := new(Eployee) //创建一个空对象
err := json.Unmarshal([]byte(jsonStr),e) //将json字符串放入对象
if err !=nil {
t.Error(err) //判断是否成功
}
if v,err:=json.Marshel(e);err==nil { //把对象变成json字符串
fmtPrintln(string(v))
}
接收参数
func main() {
var name = flag.String("参数名", "默认值", "参数介绍")
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", "question")
flag.PrintDefaults()
} // 重置help介绍
flag.Parse()
fmt.Printf("hello %s!", *name) //这里的name是个地址
}
类型断言
//方式一
tmp := []int{1,2,3}
_, ok := interface{}(tmp).([]int) //必须为接口
// ok为True
//方式二
elem, err := getElement(tmp)
func getElement(containerI interface{}) (elem string, err error) { //函数输入可以自己转换类型,输出可以不在return后
switch t := containerI.(type) {
case []int:
elem = t
case map[int]string:
elem = t
default:
err = fmt.Errorf("unsupported container type: %T", containerI)
return
}
return
}