golang基础语法小结 | 青训营笔记

166 阅读8分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记。

下面是对golang语法的一点小总结。

--GO是强变量类型语言

字符串类型数据可以通过“+”来拼接,也可以用=来比较两个字符串,go里大部分运算符号的优先级跟C一样。

--Go有两种变量声明方式

第一种:

var 变量名 = 值

这种方式一般会自动推导变量的类型,如果有需要,也可以显式的写出变量类型。例如:

var b, c int = 1,2

第二种:

变量名 := 值

是一条短变量声明,最简洁,但只能用在函数内部,而不能用于包变量。

--Go里面的常量声明

const 变量名 (类型) = 值

Go里面的常量没有确定的类型,会根据使用的上下文自动确定类型。

--Go中的if语句

if语句的条件外不需要写括号,但是"{"必须与if语句同行,并且在行末尾.

if 条件 {

代码。。。 

} else { 

代码。。。 

}

--Go只有for循环

for 语句1,条件,语句3{ //同样 { 必须同一行并且位于末尾

   代码。。。 
   (break/continue)
} 

其中,语句1,条件,语句3都可以省略,全部省略就是一个死循环。 break,continue分别为跳出循环 和 跳过这次循环

--Go的switch语句

Go的switch语句格式与C语言很像,不过有几个不同

switch 变量 { //在格式上,Go语言很强硬,"{”就是必须在同行末尾 
    case 1:代码。。 
    case 2:代码。。  
    default:代码。。//所有case代码都不执行的话,就默认执行这个。
} 

Go的switch与C有几点不同,每一个case的代码后面不需要跟着break; 在C中,Switch语句的case代码后面都需要一个break;不然就会把后面的所有case代码都运行一遍。 在Go中,switch语句的case代码运行完后会自动跳出switch语句。 C中的swtich语句只能使用整型变量,而Go中的switch语句可以使用任意类型变量,比如字符串,结构体。

Go中的switch甚至可以取代任意的if-else语句,即省略变量,然后直接在case后面接条件,例如

switch { 
    case 条件1:代码。。。 
    case 条件2:代码。。。 
    default:代码。。。//条件1和2都不满足的话,就默认执行这里的代码。
}

--Go中的数组声明方式

var 数组名 [长度]类型

例如

var a [5]int //声明了一个能容纳5个int型变量的数组a

数组的优点是随机存取,就是想读哪个就读哪个。 缺点是长度固定。所以一般使用切片

--Go中的切片

切片是可变长度的数组,可以任意时刻去更改切片。 切片的声明:

变量名 := make([]类型,长度)

切片可以跟数组一样使用,比如用s[索引值]来读取值,或者更改值, 切片用append来追加元素,具体如下

切片名 = append(切片名,元素1,元素2...)

因为容量不够的时候会发生扩容,变成新的切片,所以要赋值回去 可以使用copy函数来复制一个切片,具体如下

    切片2 := make([]类型,len(切片1))
    copy(切片2,切片1

切片可以用python那种区间读取的方法,也是左闭右开,例如

s := []String{"a","b","c","d',"e","f"}

s[2:5]表示从下标2到5的元素,结果是c,d.e。

s[:5]的表示从0到5的元素,结果是a,b,c,d,e。

s[2:]表示从2到最后的元素,结果是c,d,e,f。

--Go中的map类型

map就是其他语言中的哈希表类型,声明如下

变量名 := make(map[键(key)类型] 值(value)类型)

基本操作:

map名[键值] = 值 //赋值操作 

len(map名) //求map里键值对的个数 

r, ok := map名[键值] //ok中存储了是否存在当前键的一个变量,是布尔型的,即true和false 

delete(map名,键值)//删除map中的某一个键值对

map的遍历是随机顺序的,不以字母或者数字为顺序。

--Go中的range

range是用来快速简洁地遍历切片(slice)和map的,用法如下

for 变量名1,变量名2 := range map(或切片)名{
    代码。。。。
}

遍历map时,变量名1表示键,变量名2表示值,如果你不需要用到变量名1,那就需要把变量名1改为下划线_, 表示这个变量没用上,Go不允许有没派上用场的变量存在。

--Go中的函数

Go的函数声明格式如下

func 函数名(参数1 参数类型,参数2 参数类型。。。。)(返回值名 返回值类型1, 返回值名 返回值类型2){ 

函数代码

return 返回值1,返回值2

} 

Go在实际的业务逻辑代码里面经常返回多个值,第一个值是真正的结果,第二值是错误信息。

--Go有指针

不过Go指针的用途比较有限,课上提到的就是对传入的参数进行修改,例如:

func f1 (n *int){
    *n += 1
}
func main(){
    n:=5
    f1(&n)
    fmt.Println(n) //7
}

--Go的结构体

Go的结构声明方法。

   type 结构体名称 struct{
       成员名1 类型
       成员名2 类型 
       。。。 
   } 

初始化

变量名1 := 结构体名{成员名1:值1,成员名2:值2}

变量名2 := 结构体名{值1,值2}

变量名3 := 结构体名{成员名1:值1} 

访问结构体成员

变量名1.成员名

--Go的结构体方法

有点类似类方法,定义方法如下

func (结构体名 ( *)结构体类型) 方法名 (参数1 类型,参数2 类型。。。){

    函数代码。。。 

}

(结构体名 (* )结构体类型)这一部分可以用指针也可以不用指针,用了指针就可以对结构体进行修改。

结构体方法的调用格式如下:

结构体变量名.方法名(参数1,参数2...)

--Go的错误处理

在Go里面,符合习惯的就是使用一个单独的错误返回信息来进行传递错误信息。Go能清晰地知道是哪个函数返回了错误,并且能用简单的if-else处理错误。 在函数声明时,在函数的返回值类型中加一个 error类型,这就代表这个函数可能会返回错误,在函数实现的时候,如果要return,那就得同时return两个值,如果没出错,就return 正常结果, nil,如果出错了,就return nil,erros.New("错误信息")erros.New是创建错误的类型。 在调用可能返回错误的函数的时候,需要写两个变量,例如

u,err := findUser([]user{{"wang","1024"}},"wang") 

然后判断err是否存在,存在就要做一个相应的操作,例如

if err != nil{
  对应的操作。。。 
} 
。。。
使用真正的返回值u。。

--Go的字符串格式化

fmt.Println(...)

fmt.Printf("...",变量1,变量2...)

其中Printf可以使用%v来打印任何变量,不用去区分什么%d,%f,%s这些,%+v会打印更详细,%#v打印会进一步详细。%.2f打印保留2位小数的浮点数。

--Json处理

当你有了一个Go结构体之后,你只需要把成员名的首字母改成大写, 就可以调用 json.Marshal()方法来将结构体序列化成一段十六进制代码。要打印时使用string()就能打印出对应的字符串。 序列化后的字符串可以使用json.unmarshal()方法去反序列化到一个空变量里。 实例代码:

 package main
 import(
     "encoding/jason"
     "fmt"
 )
 
 type userInfo struct{
     Name string
     Age int `json:"age"`  //让他打印的时候Age显示为“age”,注意不是单引号,是键盘上esc下面那个键的符号`
     Hobby []string
 }
 
 func main(){
     a := userInfo{Name:"wang", Age:18,Hobby:[]sting{"Golang","TypeScript"}}
     buf, err := json.Marshal(a) //序列化
     if err != nil{
         panic(err)
     }
     fmt.Println(buf)  //[123,34,78,97...]
     fmt.Println(string(buf)) //{"Name":"wang","age":18...}
     
     var b userInfo
     err = json.Unmarshal(buf,&b) //反序列化到b中。
     if err != nil{
         panic(err)
     }
     fmt.Printf("%v\n",b)//main.userInfo{Name:"wang"...}
 }

--Go的时间处理

需要

   import(
   "time" 
   )

time.Now()快速获取当前时间。

t = time.Date(年,月,日,时,分,秒,time.UTC) 用来构造一个带时区的时间,构造完的时间带一系列方法用来返回具体的年月日时分秒。

t.Year()  //获取年
t.Month() //获取月
t.Day()   //获取日
t.Hour()  //获取时
t.Minute() //获取分

可以用t2.Sub(t1)可以得到一个时间段。可以得到他有多少分钟多少秒。

可以用t.Format("2006-01-02 15:04:05")来格式化一个时间成一个时间字符串。

"2006-01-02 15:04:05"这个是固定的。

可以用time.Parse("2006-01-02 15:04:05",←同样格式的时间字符串1)来将时间字符串1解析成时间。

time.Now().Unix()可以获取当前时间的时间戳。

--Go的数字解析

需要

import(
  "strconv" 
)

下面是一些方法

strconv.ParseFloat("1.234",64)//把字符串1.234转化为一个64位的浮点数 
strconv.ParseInt("111",10,64)//把字符串111转化为一个10进制,64位的整数 
strconv.Atoi("123")//把字符串123转化为十进制123整数

--Go生成随机数

import(
"math/rand"
"time" 
) 
rand.Seed(time.Now().UnixNano())//用时间戳来初始化随机数种子,否则会一直生成一个数。
rand.Intn(数字) //生成0-数字之间的随机数