Go 语言入门指南:基础语法和常用特性解析(下)
前两天刚学完了切片如何操作,今天继续学习GO语言的基础语法
映射
映射是Go语言中的一种内置的数据结构,类似于其他语言中的字典或哈希表 使用make
来创建空map 第一个类型指定为string
, 而第二个类型指定为int
。可以通过方括号对键值对进行写入和读取。通过delete
可以删除键值对。
go
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
//读取键值对的第二种方式, 通过ok来判断是否存在, 不存在的就是0 ok为false
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)
range
使用range可以快速遍历数组、切片和映射,
遍历数组或切片时,它会返回每个元素的索引和值。如果不需要索引,可以忽略它。而遍历映射时,则会返回键值对
go
nums := []int{2, 3, 4}
sum := 0
for i, num := range nums {
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
}
函数
在Go语言的业务中,函数通常会返回多个值,比如第一个值返回函数的结果,第二个值则返回错误信息, 并且函数对输入的参数都是后知的。
go
func add(a int, b int) int {
return a + b
}
func add2(a, 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++, GO语言的指针操作空间比较有限,但也能正常使用
go
func add2(n int) {
n += 2
}
func add2ptr(n *int) {
// 根据n的指针获取n的值 让它加2
*n += 2
}
func main() {
n := 5
add2(n)
fmt.Println(n) // 5
add2ptr(&n) // 将n的指针传入函数
fmt.Println(n) // 7
}
结构体
定义结构体, 可以通过以下方式对结构体进行赋值
go
type user struct {
name string
password string
}
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"
结构体方法
顾名思义, 专属于结构体的方法,就不需要每次调用的时候都把结构体传进去了。 在函数名称前面加一个括号()
在里面定义结构体,就能使得一个函数变成类成员函数。
go
func (u user) checkPassword(password string) bool {
return u.password == password
}
func (u *user) resetPassword(password string) {
u.password = password
}
a := user{name: "wang", password: "1024"}
a.resetPassword("2048")
错误处理
在Go语言中,错误是通过在函数里面的err来显示的 当需要把错误结结果显示时,可以采用erros.New
方法
go
// 在函数里面加一个err返回值
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")
}
// 当err存在时, 进行处理
u, err := findUser([]user{{"wang", "1024"}}, "wang")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(u.name) // wa
字符串操作
在GO语言的标准库strings
包里,有非常多的字符串操作函数,可以通过以下方法对字符串进行操作:
go
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 为什么这里有6个字节 因为utf-8 一个汉字3个字节 所以在这里的长度就是6了。
}
字符串格式化
字符串的格式化是这样的,println函数打印了会自动换行 而print函数则不会自动换行
scss
fmt.Println(p) // {1 2}
fmt.Printf("s=%v\n", s) // s=hello
与C语言类似,但在这里%V
是值的默认格式,会打印出后面用于替换的变量。
拓展:
%+v
:这是值的扩展格式,它不仅会打印变量的值,还会打印出字段的名称。
%#v
:这是值的Go语法格式,它会打印出变量的值,并且包括类型信息。对于结构体,它会显示完整的类型名称和字段名称。
JSON处理
在GO语言中,对于一个结构体而言,只要保证每个字段的首字母为大写,那么结构体就能用json.Marshal函数进行序列化
go
buf, err := json.Marshal(a) //在这里, a是一个自定义的结构体, 并且每个字段首字母都是大写。
序列化以后会变成一个JSON字符串,不能直接打印看到它的值,需要进行反序列化才能看到。当然也可以通过在结构体中定义json的tag
来对序列化后的字符串字段进行自定义:
go
type userInfo struct {
Name string
Age int `json:"age"` //加了json的tag 序列化以后不是Age
//而是age 也可以用`-`标签来忽略这个字段
}
时间处理
在GO语言中,标准库time包中,定义了time.now方法可以快速获取当前时间。
css
now := time.Now()
同时,与其他语言的time不一样的是,它的Format用的是一个确定的时间 同时可以用parse来反解析成time类型
css
t := time.Date(2022, 3, 27, 1, 25, 36, 0, time.UTC)
fmt.Println(t.Format("2006-01-02 15:04:05"))
t3, err := time.Parse("2006-01-02 15:04:05", "2022-03-27 01:25:36")
fmt.Println(now.Unix()) //这是获得时间戳的函数
数字解析
在GO语言中,字符串和数字的转换大多方法集中在标准库的strconv包中,常用的有parsefloat, parseint, atoi, itoa四种方法
parsefloat :针对的是float类型的字符串
parseint :可以按照指定的进制进行转换
atoi :则是快速将字符串转换为数字
itoa :则是快速将数字转换为字符串
进程信息
使用OS包中,有几个方法很方便查看进程信息
less
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()
通过Getenv和Setenv管理和查看进程变量
使用exec.command 执行了外部命令, 在/etc/host下搜索包含字符串"127.0.0.1"
的行, 之后通过CombinedOutput()
方法来捕获命令的输出
学习总结:
从入门学到现在,发现GO和市面上大部分语言差不多,不过也有自己的特性,感觉比python和java要难一点。但总体来说还是能够学会的,
Go语言的语法简洁,没有过多的复杂性,代码清晰和易于维护。它的表达力强,能够在少量的代码中实现复杂的逻辑,这对于大型项目的开发来说是一个巨大的优势。加油,我会继续学习