这是我参与「第五届青训营」笔记创作活动的第2天!
今天继续进行对Go语法基础剩余部分的学习!
Go语言基础语法2
函数
与其他语言不同,Go中变量类型后置。 第一个返回两数相加和,第二个用map返回错误信息
func add(a int, b int) int {
return a + b
}
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
指针
相较于c和c++比较有限,主要用于对常用的参数进行修改
//n=5,第一个仍为5,第二个为7
//不能实现自增
func add2(n int) {
n + = 2
}
//通过指针实现参数的自增
func add2ptr(n *int) {
*n + = 2
}
结构体
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
}
结构体方法
相当于c++类成员函数,可以操作类的任意对象,可以访问对象中的所有成员
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 语言通过内置的错误接口提供了非常简单的错误处理机制。
error类型是一个接口类型,这是它的定义:
type error interface { Error() string }
type user struct {
name string
password string
}
// 定义函数finduser(目的是匹配结构体中的name值)
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")
//如果error存在,打印并退出
if err != nil {
fmt.Println(err)
return
}
fmt.Println(u.name) // wang
if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil {
fmt.Println(err) // not found
return
} else {
fmt.Println(u.name)
}
}
字符串操作
在标准库strings包中有很多字符串工具函数(常见函数如下)
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
获取字符串长度
字符串格式化
一般在输出时我们用Println表示
在用Printf表示时:
Go中可用%v表示任意类型的变量(c语言中需用%d,%f来表示不同的变量)
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) // p={x:1 y:2}
fmt.Printf("p=%#v\n", p) // p=main.point{x:1, y:2}
f := 3.141592653
fmt.Println(f) // 3.141592653
fmt.Printf("%.2f\n", f) // 3.14
}
JSON
JavaScript对象表示法(JSON)是一种用于发送和接收结构化信息的标准协议。
JSON是对JavaScript中各种类型的值——字符串、数字、布尔值和对象——Unicode本文编码。它可以用有效可读的方式表示基础数据类型和数组、slice、结构体和map等聚合数据类型。
将一个Go语言中类似的结构体slice转为JSON的过程叫编组(marshaling)。编组通过调用json.Marshal函数完成:
a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Golang", "TypeScript"}}
buf, err := json.Marshal(a)
if err != nil {
panic(err)
}
fmt.Println(buf) // [123 34 78 97...]
fmt.Println(string(buf)) // {"Name":"wang","age":18,"Hobby":["Golang","TypeScript"]}
为了生成便于阅读的格式,另一个json.MarshalIndent函数将产生整齐缩进的输出。 该函数有两个额外的字符串参数用于表示每一行输出的前缀和每一个层级的缩进:
buf, err = json.MarshalIndent(a, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(buf))
时间处理
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 时间戳
数字解析
//进制转换
f, _ := strconv.ParseFloat("1.234", 64)
fmt.Println(f) // 1.234
n, _ := strconv.ParseInt("111", 10, 64)
fmt.Println(n) // 111
n, _ = strconv.ParseInt("0x1000", 0, 64) //0代表自动识别进制
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
进程信息
// 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
总结
Go语言的基础语法与C和Java还是有一些共同之处,但也有许多新的东西和很多不同的用法,在这一节学习中我对于JASO和错误处理的使用有很多不理解的地方,Go的基础语法也掌握的不是很牢固,希望在后续的学习中能够熟悉并运用!