初识Go语言 青训营笔记第一课
这是我参与【第五届青训营】伴学笔记创作活动的第1天
什么是Go语言?
Go(The Google Programming Language)语言是谷歌2009年发布的第二款开源编程语言,是一种静态型、编译型并自带垃圾回收和并发的编程语言。 Go语言专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速度,而且更加安全、支持并行进程。Go支持面向对象,而且具有真正的闭包(closures)和反射 (reflection)等功能。
Go语言特点:
高性能、高并发:语言性能上和java相近,go语言的并发基于goroutine,类似于线程,但并非线程,可以理解为一种虚拟线程。go语言运行时会合理参与调度goroutine,并将goroutine合理分配到各个cpu中,最大限度地使用cpu性能
语法简单、学习曲线平缓:与c、java语言相似
丰富的标准库,涵盖网络、系统、加密、编码、图形等方面
完善的工具链:Go语言里面内置了很多工具链,最好的应该是gofmt工具,自动化格式化代码
静态链接:在默认情况下是静态链接
快速编译:go语言利用自己的特性实现并发编译,最开始并发编译的最小元素是包,后来是函数,整体编译速度提高
跨平台:Go引用了plan9的代码
垃圾回收:内置runtime,支持垃圾回收,这属于动态语言的特性之一
Go语言的基础语言
2.1 基础语法-helloworld
package main
import "fmt"
func main() {
fmt.Println("hello world!")
}
main主函数类似于c语言中的int main(),Go语言同时存在函数和方法,fmt.Println()类似于java中的System.out.println()。将一段数据打印在标准输出流中。
在Go语言中;不是必要的,不用每行末添加;
Println中的p是大写的,在Go语言中,函数或方法首字母大写意味着可被其他包调用,否则只能在该包被调用。
2.2 基础语法-变量
Go语言的变量类型是后置的,这样创建一个类型为int的变量:
var a int=2
也可同时声明多个变量:
var b, c int = 1, 2
Go语言支持变量类型自动推断,类型可以省略:
var d = true
也可显示变量类型:
var e float64 //浮点值的默认类型为float64
可以:=简化来声明变量
f :=1
最后使用const关键字来创建常量:
const h = 500 //const无法确定类型,根据上下文自动确定类型
2.3 基础语法-if-else
package main
import "fmt"
func main() {
if 7%2 == 0 {
fmt.Println("7 is elen")
} else {
fmt.Println("7 is odd")
}
}
if后不像其他语言加上括号,在括号中写入表达式,Go语言可以不写括号
2.4 基础语法-for循环
-Go语言中只有for循环
for n := 2; n < 5; n++ {
if n%2 == 0 {
continue
} else {
fmt.Println(n)
}
}
和if一样,在for后不用加括号,但是分号不要省略,一定要记住
2.5 基础语法-switch
默认不用加break
a := 3
switch a {
case 1:
fmt.Println("one")
case 2:
fmt.Println("two")
case 3:
fmt.Println("three")
default:
fmt.Println("other")
}
2.6 基础语法-数组
var c [2][3]int
for i := 0; i < 2; i++ {
for j := 0; j < 3; j++ {
c[i][j] = i + j
}
}
fmt.Println(c)
声明数组类型时,也是在后面写上类型,声明时可以简化i :=0
2.7 基础语法-切片
切片是一种对数组的抽象,可以动态地管理数组中的元素,切片是一个指向底层数组的指针,包含三个属性:指针,长度和容量
s := make([]string, 3)
s[0] = "a"
s[1] = "b"
s[2] = "c"
fmt.Println(s[2])
fmt.Println(len(s))
s = append(s, "e", "f") //通过内置函数append() 动态增加元素
fmt.Println(s)
d := make([]string, len(s)) //可通过函数make()创建,返回一个初始化长度为len的切片
copy(d, s) //复制
fmt.Println(d)
fmt.Println(s[2:5]) //取出第二个到第五个元素之间,不包括第五个元素
good := []string{"g", "o", "o", "d"}
fmt.Println(good)
2.8 基础语法-map
Go语言中map为一种内置数据结构,用于存储键值对,键为可比较的数据类型(如字符串、数字),值为任何数据类型
m := make(map[string]int) //利用make() 创建空map,键为字符串,值为整数
m["one"] = 1 //赋值,one为键,1为值
m["two"] = 2
fmt.Println(m)
fmt.Println(len(m))
fmt.Println(m["one"])
delete(m, "one") //利用delete函数删除键值对
fmt.Println(m)
m2 := map[string]int{"one": 1, "two": 2} //直接赋值
var m3 = map[string]int{"one": 1, "two": 2}
fmt.Println(m2, m3)
2.9 基础语法-range
在 Go 中,range 关键字用于遍历数组、切片、字符串、map 和通道中的元素。对于数组、切片和字符串,它将返回每个元素的索引和值。对于 map,它将返回每个键和值。对于通道,它将返回每个从通道中接收到的值。
nums := []int{2, 3, 4}
sum := 0
for i, num := range nums { //遍历数组
sum += num
if num == 2 {
fmt.Println("index:", i, "num:", num)
}
}
fmt.Println(sum)
m1 := map[string]string{"a": "A", "b": "B"} //遍历map
for k, v := range m1 {
fmt.Printf(k, v)
}
for k := range m1 { //对于通道,可以在循环中使用range从通道中接收数据,直到该通道关闭
fmt.Println("key", k)
}
for _, k := range m1 { //遍历中可使用_来忽略该变量
}
2.10 基础语法-函数
Go语言中,函数为一组可重用的代码块,可在程序中多次调用,定义一个函数需要使用关键字func ,函数名称,参数,返回值
func add(a int, b int) int { //Go语言的类型为后置的,a int
return a + b
}
func add2(a, b int) int { //简化,在一行同时声明多个变量
return a + b
}
//Go中的函数可以有多个返回值,m键值对,v返回结果,ok布尔类型判读是否相同
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
func main() {
res := add(1, 2) //调用函数使用函数名称和传递给函数的参数
fmt.Println(res)
re := add2(2, 2)
fmt.Println(re)
v, ok := exists(map[string]string{"a": "A"}, "a")
fmt.Println(v, ok)
}
2.11 基础语法-指针
Go 语言中,指针是指向一个变量的地址的变量。指针存储了变量的内存地址,因此可以通过指针来访问和更改变量的值。创建指针需要使用 & 符号,它表示取地址运算符。
func add3(n int) { //函数中的参数默认为传值调用,函数会接收一个变量的副本,而不是变量本身
n += 2
} //无效,运行不出来
func add3p(n *int) { //函数中的参数为一个指针,它指的是main函数中的n变量
*n += 2
}
func main() {
n := 5
add3(n) //对n变量的更改不会影响main函数的n变量
fmt.Println(n)
add3p(&n) //函数中对*n的更改会影响到main函数中的n变量,需加上取地址符&来获取变量的内存地址
fmt.Println(n)
}
2.12 基础语法-结构体
在 Go语言中,结构体是一种用户定义的数据类型,它可以用来组合不同类型的数据。结构体是一组字段(类似于其他语言中的成员变量或属性)。 定义结构体需要使用关键字 type 和 struct。每个字段都有一个名称和类型。
type user struct {
name string
password string
}
func main() {
a := user{name: "wang", password: "123"}
b := user{"wan", "123"}
c := user{name: "liu"}
c.password = "132"
var d user
d.name = "wa"
d.password = "111"
fmt.Println(a, b, c, d)//四种方法进行赋值
fmt.Println(checkPassword(a, "haha"))
fmt.Println(checkPassword2(&a, "haha"))
}
func checkPassword(u user, password string) bool {
return u.password == password
}
func checkPassword2(u *user, password string) bool {
return u.password == password
}
2.13 基础语法-结构体方法
结构体可定义方法,方法通过结构体实例调用
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: "111"}
a.resetPassword("2021")
fmt.Println(a.checkPassword("2021"))
}
2.14 基础语法-错误处理
在 Go 语言中,错误处理是一个重要的部分。Go 提供了一种简单的方法来处理错误,即将错误作为函数的返回值。
在 Go语言中,错误是一个内置的 error 类型,该类型实现了 error 接口。在错误发生时,函数可以返回一个 error 值
type user struct {
name string
password string
}
//需返回两个值,其中一个为错误信息
func findUser(users []user, name string) (v *user, err error) {
for _, u := range users {
if u.name == name {
return &u, nil //没有错误则返回原本结果和一个nil
}
}
return nil, errors.New("not found")
}
func main() {
u, err := findUser([]user{{"wang", "1024"}}, "wang")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(u.name) //错误不为nil时,运行成功
if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil {
fmt.Println(err)
return
} else {
fmt.Println(u.name)
}
}
2.15 基础语法-字符串操作
func main() {
a := "hello"
b := "你好呀"
fmt.Println(strings.Contains(a, "ll")) //是否包含有
fmt.Println(strings.Count(a, "l"))
fmt.Println(strings.HasPrefix(a, "he")) //测试字符串是否以he为前缀
fmt.Println(strings.HasSuffix(a, "llo")) //测试字符串是否以llo为后缀结尾
fmt.Println(strings.Index(a, "ll"))
fmt.Println(strings.Join([]string{"he", "llo"}, "-")) //连接其第一个参数的元素以创建单个字符串,分隔符-,。放在字符串中的元素之间
fmt.Println(strings.Repeat(a, 2)) //重复
fmt.Println(strings.Replace(a, "e", "E", -1)) //替换,-1n<0,表示替换次数没有限制
fmt.Println(strings.Split("a-b-c", "-")) //分割,去掉分隔符
fmt.Println(strings.ToLower(a)) //小写
fmt.Println(strings.ToUpper(a)) //大写
fmt.Println(len(a)) //字符串长度
fmt.Println(len(b)) //一个文字占3个长度
}
2.16 基本语法-字符串格式化
type point struct {
x, y int
}
func main() {
s := "hello"
n := 123
p := point{1, 2}
fmt.Println(s, n)
fmt.Println(p)
fmt.Printf("s=%v\n", s) //printf 字符串,数据格式化输出
fmt.Printf("n=%v\n", n)
fmt.Printf("p=%v\n", p)
fmt.Printf("p=%+v\n", p)//%+v添加字段名(结构体)
fmt.Printf("p=%#v\n", p)//%#v相应值的go语法表示
f := 3.1415926
fmt.Println(f)
fmt.Printf("%.2f\n", f)
}
2.17 基础语法-JSON处理
json是一种数据交换格式,常用于前后端数据传输,变量首字母大写才可以转成json
type userInfo struct {
Name string
Age int `json:"age`
Hobby []string
}
func main() {
a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Golang", "typeScript"}}
//若编码成功,err赋于零值nil,变量buf为一个进行json格式化之后的[]byte类型
buf, err := json.Marshal(a) //将数据编码成json字符串
//指针,切片,映射,通道,函数,接口零值为nil
if err != nil {
panic(err) //终止运行
}
fmt.Println(buf)
fmt.Println(string(buf))
buf, err = json.MarshalIndent(a, "", "\t") //用缩进对输出进行格式化,1想要编成的json结构体,2前缀通常设置为""即可,3缩进通常设置为\t即可
if err != nil {
panic(err)
}
fmt.Println(string(buf))
var b userInfo
err = json.Unmarshal(buf, &b) //将json字符串解码到相应数据结构
if err != nil {
panic(err)
}
fmt.Printf("%#v\n", b)
}
2.18 基础语法-时间处理
Go语言中使用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)
//输出年份,月份,天数,小时,分钟
fmt.Println(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute())
//格式化时间,类似于java语言中的yyyy-MM-dd
fmt.Println(t.Format("2020-1-1 15:12:11"))
diff := t2.Sub(t)
fmt.Println(diff.Minutes(), diff.Seconds())
t3, err := time.Parse("2020-1-1 15:12:11", "2022-1-1 21:11:11")
if err != nil {
panic(err)
}
fmt.Println(t3 == t)
fmt.Println(now.Unix())
}
2.19基础语法-数字解析
strconv包是 Go 语言标准库中用于字符串与数字之间转换的包。它提供了许多函数来实现字符串和整数、浮点数、布尔值之间的转换
func main() {
f, _ := strconv.ParseFloat("3.142", 64)
fmt.Println(f)
n, _ := strconv.ParseInt("111", 10, 64)
fmt.Println(n)
n, _ = strconv.ParseInt("0x1000", 0, 64)
fmt.Println(n)
n2, _ := strconv.Atoi("123")//字符串转int int转字符串:itoa()
fmt.Println(n2)
n2, err := strconv.Atoi("AAA")
fmt.Println(n2, err)
}
2.20 基础语法-进程信息
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))
}
总结
经过第一课的认识,了解了Go语言的基本语法,认识到自己的不足,与之前所学的其他语言不太一样,还是不太理解。不太熟练,实战案例有一些难懂。放松心态去进行之后的课程学习,希望可以熟练掌握Go语言