这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天
走进go语言基础语言
什么是go语言
- 高性能、高并发
- 语法简单,学习曲线平缓
- 丰富的标准库
- 完善的工具链
- 静态链接
- 快速编译
- 跨平台
- 垃圾回收
go的基础语法
// Hello World
package main
import {
"fmt"
}
func main() {
fmt.Println("hello world")
}
go中的变量
变量的声明:
- 通过var name type = value的方式
- 通过name := value
go中的ifelse
必须加{},没有()
go中的循环
go中循环只有for循环,有{},但是没有()
go中的switch语法
与c/cpp不同的是,switch中case中不需要加break
a := 2
switch a {
case 1:
fmt.Println("one")
case 2:
fmt.Println("two")
case 3:
fmt.Println("three")
case 4, 5:
fmt.Println("four or five")
default:
fmt.Println("other")
}
go中的数组
var a [5]int
a[4] = 100
b := [5]int{1, 2, 3, 4, 5}
var twoD [2][3]int
go中数组的特点是长度固定,而切片的长度是不固定的
go中的切片
go中切片的长度是不固定的,可以追加元素,在追加的时候可能是切片的容量增大。我们可以用make来创建一个切片,可以像数组一样去取值,使用append来追加元素。
在make方法中,有两个形参,一个是用来存放元素的数组类型,另一个是初始化的长度
在append方法中,必须将append的返回值返回给原变量,因为其原理是存储了一个长度、一个容量、一个指向一个数组的指针,在你执行append操作的时候,如果容量不够的话,会扩容并返回新的切片
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]
}
go中的map
数据类型和其他语言相似,由于使用hash算法,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)
}
go中的range
可以使用range快速遍历go中的数组,切片,map,通道,在数组和切片中返回元素的下标和元素值,在map中返回key-value对。与python相似,不需要的量可以使用下划线代替
go中的函数
如果有多个返回值
func function_name (para_name para_type,...) re_type {
}
go中的指针
与c中相似,存在指针类型,只是*在前指针类型在后,此外取地址符不变
go中的结构体
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
}
go中的结构体方法
结构体的属性和结构体的函数是分离的
go中的结构体方法与其他语言的类成员函数相类似
在实现结构体的方法的时候有两种写法,一种是带指针的,另一种是不带指针的。这个他们的区别的话是如果你带指针的话,那么你就可以对这个结构体做修改,如果不带指针,那么你实际上操作的是这个结构体变量的拷贝,你就无法对结构体进行修改
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
}
go中的字符串操作
package main
import (
"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-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
}
go中的进程信息
在go里面,我们能够用os.Args来得到程序执行的时候的指定的命令行参数。比如我们编译的一一个二进制文件,command。后面接 abcd来启动,输出就是os.Args会是一个长度为 5的slice ,第一个成员代表二 进制自身的名字。我们可以用os.Getenv("PATH")来读取环境变量。
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("-----------")
fmt.Println(os.Getenv("PATH")) // /usr/local/go/bin...
fmt.Println("-----------")
fmt.Println(os.Setenv("AA", "BB"))
fmt.Println("-----------")
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
}
go语言的实战案例
生成随机数
与python相同,使用随机数函数前,需要设置随机数种子(虽然两者不设置随机数种子带来的后果不同)