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

85 阅读4分钟

这是我参与【第五届青训营】伴学笔记创作活动的第一天。

一        Go语言简介及其基础语法

1.1    Go语言的特点

1.     高性能、高并发

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

3.     丰富的标准库

4.     完善的工具链

5.     静态链接

6.     快速编译

7.     跨平台

8.     垃圾回收

1.2    使用go语言的公司

字节跳动、谷歌、Facebook等

1.3    字节选择go的原因

1.     性能

2.     适合web业务

3.     早期团队偏好

4.     部署简单、学习成本低

5.     内部框架

1.4    开发环境

Go语言安装:go.dev/

Go语言IDE(Goland):www.jetbrains.com/zh-cn/go/

Git配置:goproxy.cn/

1.5    基础语法-Hello World

package main

import (
"fmt"
)

func main() {
fmt.Println("hello world")
}

第一行代表文件属于main包的一部分,也即程序的入口包,说明该文件是程序的入口文件;第三行导入的标准库里的fmt包,用于标准化io;第七行main函数开始调用了fmt包里面的Println()函数打印出了”hello world”

1.6    基础语法-变量

package main



import (

   "fmt"

   "math"

)



func main() {



   var a = "initial"



   var b, c int = 1, 2



   var d = true



   var e float64



   f := float32(e)



   g := a + "foo"

   fmt.Println(a, b, c, d, e, f) // initial 1 2 true 0 0

   fmt.Println(g)                // initialapple



   const s string = "constant"

   const h = 500000000

   const i = 3e20 / h

   fmt.Println(s, h, i, math.Sin(h), math.Sin(i))

}

要点:

字符串可用’+’拼接

声明变量的方式:var name(,name…) (type) = value…   (可以不赋初值)

或者 name := 表达式

1.7    基础语法-条件与循环

If后面不加括号,而执行的语句必须在大括号内

没有while 和 do while,只有for循环,也没有小括号

Switch不需要break即可终结分支,且对任意变量类型都适用,甚至可以用表达式作为case

1.8    基础语法-数组

package main



import "fmt"



func main() {



   var a [5]int

   a[4] = 100

   fmt.Println("get:", a[2])

   fmt.Println("len:", 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)

}

声明方式:var name [size] (type) {value…}

或者 name := [size] (type) {value…}

1.9    基础语法-切片

package main



import "fmt"



func main() {



   s := make([]string, 3)

   s[0] = "a"

   s[1] = "b"

   s[2] = "c"

   fmt.Println("get:", s[2])   // c

   fmt.Println("len:", len(s)) // 3



   s = append(s, "d")

   s = append(s, "e", "f")

   fmt.Println(s) // [a b c d e f]



   c := make([]string, len(s))

   copy(c, s)

   fmt.Println(c) // [a b c d e f]



   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"}

   fmt.Println(good) // [g o o d]

}

声明方式:name := make(,size)

添加方式:append(slice,var)

访问长度:len(slice)

取元素方式:slice[fnum:lnum+1]

1.10           基础语法-map

package main



import "fmt"



func main() {

   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["unknow"]) // 0



   r, ok := m["unknow"]

   fmt.Println(r, ok) // 0 false



   delete(m, "one")



   m2 := map[string]int{"one": 1, "two": 2}

   var m3 = map[string]int{"one": 1, "two": 2}

   fmt.Println(m2, m3)

}

声明方式:var:= make(map[keyType]valueType)

访问方式var[key],返回value和该value是否存在的bool值

1.11           基础语法-range

for index,var := range slice/array/map{

 

}

1.12           基础语法-函数

可返回多个值(错误信息)

变量类型后置

1.13           基础语法-指针

可在函数内修改传参

 

1.14           基础语法-结构体

package main



import "fmt"



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"



   fmt.Println(a, b, c, d)                 // {wang 1024} {wang 1024} {wang 1024} {wang 1024}

   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

}

声明方式: var := structName{segment1:value1,segment2:value2…}

可用’.’来访问字段,’.’前可以是变量,也可以是指针

可在结构体中定义函数

package main



import "fmt"



type user struct {

   name     string

   password string

}



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

}

 

1.15           基础语法-错误处理

在返回值类型里添加一个error类型

1.16           字符串操作

参阅studygolang.com/pkgdoc

可以用”%v”格式化输出任意类型的变量

1.17           Json操作

json.Marshal()函数可以把结构体序列化输出为字符串,前提是结构体中每个字段名的首字母为大写字母,或者每个字段用 json”reName”表明其json字段名(这样才能用小写或下划线开头)

可以用json.Unmarshal()函数把这个序列化字符串再反序列会变量

1.18           事件处理

package main

import (
"fmt"
"time"
)

func main() {
now := time.Now()
fmt.Println(now) // 2022-03-27 18:04:59.433297 +0800 CST m=+0.000087933
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-27 01:25:36 +0000 UTC
fmt.Println(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute()) // 2022 March 27 1 25
fmt.Println(t.Format("2006-01-02 15:04:05"))                    // 2022-03-27 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 {
panic(err)
}
fmt.Println(t3 == t)    // true
fmt.Println(now.Unix()) // 1648738080
}

 

可以用time.now()快速获取当前时间

也可以用time.Date构造一个带时区的时间

可用now.Unix获取unix时间戳

1.19           数字解析

在strconv包里

ParseInt、ParseFloat、Atoi等,把字符串转换为数字

1.20           进程信息

package main

import (
"fmt"
"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]
fmt.Println(os.Getenv("PATH")) // /usr/local/go/bin...
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
}

 

可用os.Args获取进程的参数信息

用os.Getenv()来获取环境变量

用os.Setenv()来写入环境变量

用exec.Command来启动子进程,用CombinedOutput()获取返回值

二        Go语言实战

2.1    猜字谜游戏

2.1.1           生成随机数

package main

import (
"fmt"
"math/rand"
"time"
)

func main() {
maxNum := 100
rand.Seed(time.Now().UnixNano())
secretNumber := rand.Intn(maxNum)
fmt.Println("The secret number is ", secretNumber)
}

首先要设定随机数种子,一般用当前时间的unix时间戳来设定该种子。否则每次种子是相同的,则随机序列也相同,无法得到随机数

2.1.2           读取用户输入

package main

import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
"time"
)

func main() {
maxNum := 100
rand.Seed(time.Now().UnixNano())
secretNumber := rand.Intn(maxNum)
fmt.Println("The secret number is ", secretNumber)

   fmt.Println("Please input your guess")
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
fmt.Println("An error occured while reading input. Please try again", err)
return
}
input = strings.Trim(input, "\r\n")

   guess, err := strconv.Atoi(input)
if err != nil {
fmt.Println("Invalid input. Please enter an integer value")
return
}
fmt.Println("You guess is", guess)
}

os.Stdin是标准输入文件,读取用户的输入,用bufio.NewReader()生成其只读的视图,可以方便管理;strings.Trim()用于删除换行符