Go语言语法总结

如何你使用的是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
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值