Go语言基础语法 | 青训营

73 阅读7分钟
  1. 文件开头:package ……,表示这是……的一部分
  2. var <name> <type//若无需强调类型,可省略,将自动适配> = <value> 或者 <name> := <value> 声明变量
  3. Go语言字符串是内置类型,可以通过 + 号拼接、= 号比较等
  4. const <name> <type>=<value>来声明常量,常量无确定类型,根据使用的上下文自动确定类型
  5. Go语言if后面没有括号,if的条件后面只能有大括号,执行语句要写在下一行
  6. Go语言只有**for循环**
  7. Go语言switch case:变量不加括号,可以为任意类型,甚至可以代替if-else、默认在每个case里面都有个break,无需自己编写
  8. 数组
    var <name> [len]<type>{…,…,…}
  9. 切片: 相比数组来说长度不固定
  • make( [ ]<type>,<len>)来创建切片
  • append(<name>,<value>)来添加元素,用append添加元素要赋值给切片如:
    s=append(s, "hello")
  • copy(<name>,<name>)来拷贝切片,如下:
    c,s为两个不同的切片
    copy(c, s)
  • 有如python一样的切片操作,如下
s:= make([ ]string, 5) 
s[0]=a 
s[1]=b 
s[2]=c 
s[3]=d 
s[4]=e 
s[5]=f
fmt.Println(s[2:5]) // [c d e]
fmt.Println(s[:5]) //[a b c d f]
fmt.Println(s[:2]) //[c d e f]

10. Map//在别的语言里可能会叫字典或者哈希

  • make(map[<keytype>]<valuetype>)来创建MAP,如
    m := make(map[string] int)
  • <name>[<key>] = <value>为map添加元素,如下
    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["unknow"]) //0
  • delete(<name>, <value>)来删除 k , v 对
  • 用ok字段判断是否有该 k , v 对,如下
r, ok:=m["unknow"]
fmt.Println(r, ok) //0 false
  1. 用Range来遍历数组、切片、Map
  • 遍历数组,会返回两个值一个是索引(下标),另一个是数组的值:
//假设nums := [ ]int {2,3,4},sum := 0
for i, num := range nums {//这里可以使用_将index省略
    sum += num
    if num == 2 {
        fmt.Println("index:", i,"num:" , num) // index:0 num:2
    }
}
fmt.Println(sum) //9
  • 遍历切片:
m:=map[string]string{"a": "A", "b": "B"}
for k, v := range m {
        fmt.Println(k, v) // b 8; a A
        }
for k := range m {
        fmt.Println("key", k) // key a; key b
        }
  1. 函数
    Go语言中,变量是后置的,在大多数业务代码总中,函数总是返回多个值,第一个是真实值,第二个一般为错误信息例如:
func add(a int, b int) int {
    return a + b
}
func exists (m map[string]string, k string)(v string, ok bool) {//像这里,当该值不存在时,将返回false,false即为错误信息
    v, ok = m [k]
    return v, ok
}
  1. 指针
    Go语言的指针用法与C\C++类似,但用法没那么多和复杂,主要用于修改常用变量的值
  2. 结构体
    结构体是带类型的字段的集合
type user struct{ //结构体的定义
    name string
    password string
}

func main() {
    a := user {name :"wang", password :"1024"}
    b := user {"wang" , "1024"} 
    c := user {name: "wang"}//当带变量名输入值时,可以输入特定字段的值,未初始化的字段为空值,即int类型为0,string类型为空字符串
    c.password = "1024"
    var d user
    d.name = "wang"
    d.password = "1024"
    fmt.Println(a,b,c,d) // {wang 1024} {wang 1024} {wang 1024} {wang1024}
    fmt.Println(checkPassword(a,"haha"))   //false
    fmt.Println(checkPassword2(&a,"haha")) //false
}  

func checkPassword (u user, password string) bool {//结构体可作为函数的参数传递
    return u.password == password
}

func checkPassword2 (u *user, password string) bool {//当使用指针进行传输字符串时,可避免拷贝超大结构体所带来的资源损失
    return u.password == password
}
  1. Go语言中,可以为结构体定义结构体方法,结构体方法类似于其他语言的类成员函数,例如:
func (u user) checkPassword (password string) bool {//与JAVA类似,新声明了一个结构体后,Go可以使用“.",对结构体方法进行调用
    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")) 
}
  1. 错误处理
    Go语言中通常通过在函数中返回信息来进行错误的处理(不同于Java的异常,可以知道是哪个函数返回了错误信息)
func findUser (users[] user, name string)(v *user, err error){//这里有个error类型,表示这个函数可能会发生错误 
    for _, u := range users {
        if u.name == name {
        return &u, nil
        }
    }
    Return nil, errors.New("notfound") //这里New了一个error,error的信息为notfound
}
func main(){
    u, err := findUser([]user{{"wang", "1024"}},"wang")
    if err != nil { //error的处理
        fmt.Println(err)
        return
    }
}
  1. 字符串处理
    使用Stings包,有以下处理字符串的功能
语句结果作用
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-llo在字符串中间插入
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中文字符串可能占据不同的字符串长度
  1. 字符串格式化
type point struct{
    x, y int
}

s := "hello"
n := 123
p := point{1,2}
fmt.Println(s,n)//hello123,println是打印并换行
fmt.Println(p)//{12}

fmt.Printf("s=%v\n",s)//s=hello,可以使用%v来打印任意类型的变量
fmt.Printf("n=%v\n",n)//n=123
fmt.Printf("p=%v\n",p)//p={12}
fmt.Printf("p=%+v\n",p)//p={x:1y:2},%+v可以输出更详细的信息,如字段名称和值
fmt.Printf("p=%#v\n",p)//p=main.point{x:1,y:2},%#v可以进一步输出更详细的信息

f := 3.141592653
fmt.Println(f)//3.141592653
fmt.Printf("%.2f\n",f)//3.14,打印特定格式的浮点数
  1. JSON操作
    使用encoding/json包对Json进行操作
type userInfo struct{ //需要保证结构体的每个字段的开头字母为大写,即为Go中的公开字段
    Name string
    Age int `json:"age"` //'json: "age"这个tag将Age字段的输出变成了小写,可以以此类推修改
    Hobby[] string
}

func main() {
    a=userInfo{Name:"wang",Age:18,Hobby:[string{"Golang","TypeScript"}}
    buf,err:=json.Marshal(a)//这样,在Go中就可以直接使用json.Marshal(<name>)将JSON序列化成一个Bytes数组,这里即buf时一个bytes数组
    if err != nil {
        panic(err)
    }

    fmt.Println(buf)//[123 34 7897...],这里是一些16进制的编码
    fmt.Println(string(buf))//{"Name":"wang","age":18,"Hobby":["Golang","TypeScript"]},这里使用了强制类型转换将buf转换为string类型数组

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

    var b userInfo
    err = json.Unmarshal(buf,&b)//这里使用了json.Unmarshal(<src_name>, &<dest_name>)反序列化到一个空的变量中
    if err != nil {
        panic(err)
    }
    fmt.Printf("%#v\n",b)//main.userInfo{Name:"wang",Age:18,Hobby:[]string{"Golang","TypeScript"}}
}
  1. 时间处理:time包
func main() {
    now := time.Now() //获取当前时间
    fmt.Println(now)
    t := time.Date(2022,3,27,1,25,36,0,time.UTC)
    t2 := time.Date(2022,3,27,2,30,36,0,time.UTC)
    fmt.Println(t)//2022-03-2701:25:36+0000UTC
    fmt.Println(t.Year(),t.Month(),t.Day(),t.Hour(),t.Minute())//2022march27125
    fmt.Println(t.Format("2006-01-0215:04:05"))//2022-03-2701:25:36,格式化时间,"2006-01-0215:04:05"是Go中固定的时间格式,而不同于其他语言中使用的yymmdd……
    diff := t2.Sub(t)//两个时间相减
    fmt.Println(diff)//1h5m0s
    fmt.Println(diff.Minutes(),diff.Seconds())//65 3900,这里分别对应了上面时间段分别对应多少分钟,多少秒
    t3,err := time.Parse("2006-01-0215:04:05","2022-03-2701:25:36")
    if err != nil {
        panic(err)
    }
    fmt.Println(t3 == t)//true
    fmt.Println(now.Unix())//1648738080,这里获取了一个时间戳
}
  1. 字符串转数字:strconv包
func main(){
    f, _ := strconv.ParseFloat("1.234", 64)
    fmt.Println(f) // 1.234

    n, _ := strconv.ParseInt("111", 10, 64)//第一个参数是字符串,第二个是进制(如果是0就为自动),第三个是精度
    fmt.Println(n) // 111

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

    n2, _ := strconv.Atoi("123")
    fmt.Println(n2) // 123

    n2, err := strconv.Atoi("AAA")
    fmt.Println(n2, err) // 0 strconv.Atoi: parsing "AAA": invalid 
    syntax
}
  1. 环境:os 和 os/exec 包
func main() {
    // go run example/20-env/main.go a b c d
    fmt.Println(os.Args)//[/var/folders/8p/n34xxfnx38dg8bv_x8l62t_m0000gn/T/go-build3406981276/b001/exe/main a b c d],os.Args获取的是Go文件执行时命令行的一些参数
    fmt.Println(os.Getenv("PATH"))// /usr/local/go/bin...,os.Getenv("PATH")获取了环境变量的路径

    fmt.Println(os.Setenv("AA", "BB"))//os.Setenv( )写入环境变量
    buf, err := exec.Command("grep", "127.0.0.1", "/etc/hosts").CombinedOutput()//exec.Command( ),快速启动子进程,并获取其输入输出
    if err != nil {
        panic(err)
    }
    fmt.Println(string(buf)) // 127.0.0.1       localhost
}