GO语言基础语法 | 青训营笔记

82 阅读7分钟

主要对老师所讲到的GO语言基础中的代码以及重点进行了简单的总结,并添加了标注,加上了一些课外的拓展

特点:

  1. 高性能,高并发

  2. 语法简单/学习曲线平缓

  3. 丰富的标准款

  4. 静态链接

  5. 快速编译

  6. 跨平台

  7. 垃圾回收(无需考虑内存释放)

声明值

Go语言中的变量需要声明后才能使用,同一作用域内不支持重复声明。并且Go语言的变量声明后必须使用。

变量名:=值 有强制转换方法 如: 可以用float32() 例子:var e float64 f:=float32(e)

常量const没有固定类型 可以根据值(上下文)的类型自动确定类型 如:const s="hello"

分支 循环

if分支条件的小括号可省略,大括号不可以省略 如:

if 7%2==0{
    fmt.Println("7 is even")
}else{
    fmt.Println("7 is odd")
}

循环

GO中只有for循环 for init; condition; post { } init是变量赋一个初值,condition是循环条件,post是控制变量

(1)判断变量是否满足condition,满足则返回true,进入循环

(2)第一次循环结束,post控制变量再次进入(1),不满足则返回false,退出循环进行之后的判断

无限循环(死循环)

for{
    fmt.Println"Loop"break//结束循环
}
for j:=7;j<9;j++{
    fmt.Println(j)
}

continue 与 break

switch 分支不用break

switch a{
case 1:
    fmt.Println("one")
case 2:
    fmt.Println("two")
default:
    fmt.Println("other")
}

switch可以用来代替if 可能更加简单

t:=time.Now()
switch{
    case t.Hour()<12:
        fmt.Println("It's before noon")
    default:
        fmt.Println("it's after noon")
}

数组

var a[5] int
a[4]=100
fmt.Println(a[4],len(a))

b:=[5]int{1,2,3,4,5}
fmt.Println(b)

var twoD[2][3] int
for i:=0;i<2;i++{
for j:=0;j<3;j++{
twoD[i][j]=i+j
}
}
fmt.Println("2d",twoD)

但是在GO中更多使用的是切片,可以更多时刻去更改长度,有更多的操作

切片

不是数组或数组指针。它通过内部指针和相关属性引用数组片段,以实现变长方案

s:=make([]string,3)
s[0]="a"
s[1]="a"
s[2]="a"
fmt.Println("get:",s[2])
fmt.Println("len:",len(s))

//切片slice包括长度,容量,指向数组的指针
//s必须把append结果复制回原来的数组,执行append时容量不够会变成一个新的slice

s=append(s,"d")
s=append(s,"d","f")
fmt.Println(s)//\[a b c d e f]

c:=make(\[]string,len(s))//可以用方法直接指定长度
copy(c,s)
fmt.Println(c)

fmt.Println(s\[2:5])//\[c d e]
fmt.Println(s\[:5])//\[a b c d e]
fmt.Println(s\[2:])//\[c d e f]

good:=\[]string{"g","o","o","d"}
fmtPrintln(good)//\[g o o d]\`

Map

一种无序的基于key-value(键值对)的数据结构,Go语言中的map是引用类型,必须初始化才能使用。

map的初始值为nil,需要make()函数分配内存

m:=make(map[string]int)
m["one"]=1
m["two"]=2
fmt.Println(m)//map[one:1 two:2]
fmt.Println(len(m))//2
fmt.Println(m["one"])//1
fmt.Println(m["unknown"])//0

r,ok:=m["unknown"]//在后面加ok判断是否存在
fmt.Println(r,ok)//0,false

delete(m,"one")

m2:=map[string]int{"one":1,"two":2}//不使用make,直接给map赋值
var m3=map[string]int{"one":1,"two":2}//可以给给变量声明
fmt.Println(m2,m3)

Range(可以快速遍历)

range类似迭代器操作,返回 (索引, 值) 或 (键, 值)。 for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。

nums:=[]int(2,3,4)
for i,num:=range nums{//当不需要索引时,i可以用"_"(下划线)替换 ,即忽略
}

m:=map[string]string{"a":"A","b","B"}
for k ,v:=range m{//可以获取键值,可以只获取键或者值,不需要"_"(下划线)
}

函数 (golang的函数类型是后置的)

函数声明包含一个函数名,参数列表, 返回值列表和函数体。如果函数没有返回值,则返回列表可以省略。函数从第一条语句开始执行,直到执行return语句或者执行函数的最后一条语句。

func add(a int,b int)int{
    return a+b
}

func add(a,b int) int{
    return a+b
}

func exists(m map\[string]string,k string)(v string,ok bool){ //ok是map中判断是否存在
    v,ok=m\[k]
    retuen v,ok
}

func main(){
    res:=add(1,2)
    fmt.Println(res)//3

    v,ok:=exists(map[stirng]string{"a":"A"},"a")
    fmt.Println(v,ok)//A True

}

指针

(相较于C与C++的指针功能十分有限 主要对传过来的参数进行修改)

func add2(n int){
n+=2
}//以上代码无效,不会对参数造成影响

正确写法:

func add2ptr(n \*int){
\*n+=2
}

func main(){
n:=5
add2(n)
fmt.Println(n) //5
add2ptr(\&n)
fmt.Println(n) //7
}

结构体

带类型的字段的集合

Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念。Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性。

type user struct{
    name string
    password string
}
//结构体有多种实例化赋值方法

func main(){
a:=user{name:"wang",password:"1024"}

    b:=user{"wang","1024"}

    c:=user{name:"wang"}
    c.password="1024" 

    var d user
    d.name="wang"
    d.password="1024"

}

结构体可以作为参数,分为带指针和不带指针两种

func checkPassword(u user,password string) bool{
    return u.password==password
}

func checkPassword2(u \*user,password string)bool{
    return u.password==password
}

结构体方法


func (u user)checkPassword(password string)bool{
    return u.password==password
}

func (u user) resetPassword(password string){
    u.password=password
}

func main(){
    a:=user{name:"wang",password:"1024"}
    a.resetPassword("2048")
    fmt.Println(a.checkPassword("2048")) //true
}

错误处理 需要引用errors

不同于java,golang的错误处理可以更清楚的知道错误出现在哪个位置

func findUser(users []user,name string)(v *user,err error){
    for _,u:=range users{
        if u.name==name{
            return &u,nil
}
}
    return nil,errors New("not found")
}

func main(){
u,err:=findUser(\[]user{{"wang","1024"}},"wang")
    if err!=nil{//nil 在这里暂时理解为空
        fmt.Println(err)
        return
}
    fmt.Println(u,name)

    if u,err:=findUser(findUser[]user{{"wang","1024"}},"li");err!=nil{
        fmt.Println(err)
        return
    }else{
        fmt.Println(u.name)
    }

}

字符串操作

package mainimport (
"fmt""strings"
func main( ) {
    a := "hello"
    fmt .Println(strings.Contains(a,"ll"))/ / true
    fmt .Println(strings.Count(a,"l") )/ / 2
    fmt.Println(strings.HasPrefix(a,"he" ) )// true
    fmt.Println(strings.HasSuffix(a,"llo" ) )// true
    fmt.Println(strings.Index(a,"ll") )//2
    fmt.Println(strings.Join([]string{"he","llo"},"-")) / / he-             fmt.Println(strings.Repeat(a,2))// hellohello
    fmt.Println(strings.Replace(a,"e","E",-1))// hEllo
    fmt.Println(strings.Split("a-b-c","-"))// [a b c]
    fmt.Println(strings. ToLower(a))// hello
    fmt .Println(strings.ToUpper(a))// HELLO
    fmt.Println(len(a))// 5
    b :=“你好"
    fmt.Println(len(b))// 6
    }

字符串格式化 Println() Printf()

type point struct{
    x,y int
}

func main(){
    s:="hello"
    n:=123
    p:=point{1,2}
    fmt.Println(s,n)//hello 123
    fmt.Println(p)   //{1 2}

    fmt.Printf("s=%v\n",s)//s=hello
    fmt.Printf("n=%v\n",n)//n=123
    fmt.Printf("p=%v\n",p)//p={1,2}
    fmt.Printf("p=%+v\n",p)//+v可以输出的更加详细  p={x:1 y:2}
    fmt.Printf("p=%#v\n",p)//#v可以比+v输出的更加详细p=main.point{x:1,y:2}

    f:=3.141592653
    fmt.Println(f) //3.141592653
    fmt.Pirintf("%.2f\n",f) //3.14

}

Json处理 需要引用 encoding/json

type userInfo struct{
    Name string
    Age int     'json:"age" //这里是Tag加了之后,输出的时候Age就变成了age
    Hobby []string
}

func main(){
    a:=userInfo{Name:"wang",Age:18,Hobby:[]string{"Golang","TypeScript"}}
buf,err:=json.Marshal(a)
    if err!=nil{
        panic(err)
}
    fmt.Println(buf) //这里输出的是16进制的字符串
    fmt.Println(string(buf))//这里输出的是json格式的字符串

    buf.err=json.MarshalIndent(a,"","\t")
    if err!=nil{
        panic(err)
    }
    fmt.Println(string(buf))

    var b userInfo
    err=json.Unmarshal(buf,&b)//反序列化
    if err != nil
        panic(err)
    }
    fmt.Printf("%&v\n",b)

}

时间处理

import {
    "fmt"
    "time"
}

func main(){
    now :=time.Now()//获取当前时间(国际原子时UTC)
    fmt.Println(now)
    t:=time.Date(2022,3,27,1,25,36,0,time.UTC)
    t2:=time.Date(2022,3,27,30,36,0,time.UTC)
    fmt.Println(t)
    fmt.Println(t.Year(),t.Month(),t.Day(),t.Hour(),t.Minute())//2022 March 26 1 25
    fmt.Println(t.Format("2006-01-02 15:04:05"))//格式转换不是一些常见语言的“yy-MM-dd而是一串准确的时间2006-01-02 15:04:05(这串时间可以在time包中的文档中查看)”  2022-03-26 01:25:36
    diff:=t2.Sub(t)
    fmt.Println(diff) //1h5m0s 得到的是时间差(格式时分秒)
    fmt.Println(diff.Minutes(),diff.Seconds())//65(转化为分) 3900(转换为秒)
    t3,err:=time.Parse("2006-01-02 15:04:05","2022-03-27 01:25:36")
    if err!=nil{
        print(err)
}
    fmt.Println(t3==t)
    fmt.Println(now\.Unix)//1648738080  获得unix时间戳 1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒
}

数字解析

import {
    "fmt"
    "strconv"
}

func main(){
    f,_:=strcon.ParseFloat("1.234".64)
    fmt.Println(f) //1.234

    n,_:=strconv.ParseInt("111",10,34)
    fmt.Println(n)//111

    n,_=strconv.ParseIn("0x1000",0,64)
    fmt.Println(n)//4096

    n2.err:=strconv.Atoi("AAA")
    fmt.Println(n2,err)//返回错误

}

进程信息

import {
    "fmt"
    "os"
    "os/exec"
}

func main(){
    fmt.Println(os.Args)
    fmt.Println(os.Getenv("PATH"))
    fmt.Println(os.Setenv("AA","BB"))
    buf,err:=exec.Command("grep","127.0.0.1","/etc/hosts").CombinedOutput()
    if err!=nil{
        panic(err)
}
    fmt.Println(string(buf))//127.0.0.1 localhost
}