这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记
GoLang
package main
import(
"fmt"
)
func main(){
fmt.Println("hello world")
}
基础语法
变量声明
-
var name string = ""
- 会自动推导变量类型
-
变量 := 值
常量
- var 改成 const,Go中常量没有确定的类型,会根据上下文自动确定类型
判断
-
与C++相似
-
不同点
- if后语句没有括号
- if后必须接大括号
循环
- Go中只有for循环
- 且for循环的条件语句不需要加括号
- break和continue与C++功能相同
switch
-
switch后的变量名不需要加括号
-
Go中的switch不需要在每个case中加break语句(C++中没有break语句会继续往下跑完所有的case)
-
Go中的switch可以使用任意的变量类型,可以取代if else
-
switch { case t.Hour() < 12: fmt.Println("It's before noon") default: fmt.Println("It's after noon") }
-
数组
- 特性与C++相似
- 长度固定,真实业务代码很少直接使用
-
var a [5]int //声明一个可以存放5个int元素的数组A b := [5]int{1,2,3,4,5} //枚举声明
切片
- 可以任意更改长度
-
//make创建切片 s := make([]string, 3) //可以像数组一样赋值 s[2] = 'c' //append追加元素(用法是必须把append的结果赋值为原数组) s = append(s, "d") //len取切片长度 length = len(s) //复制切片,从后到前 copy(c, s) //同python的切片操作,但不支持负数索引 s[2:3] //[c,d]
map
- 类似C++中的哈希表
-
//make创建,第一个是key的类型,这里是string;第二个是value的类型,这里是int m := make(map[string]int) //delete删除键值对 delete(map_name, map_key) - GoLang的map是完全无序的,遍历时也不会按照字母排序,也不会按照插入顺序输出,而是随机顺序
range
- range用来快速遍历slice和map
- 遍历时会返回两个值,第一个是索引,第二个是对应位置的值
- 不需要索引就用下划线来忽略
-
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
函数
-
变量类型后置
-
支持返回多个值,实际的业务逻辑代码中几乎所有函数都返回两个值
- 第一个是真正的返回结果,第二个值是一个错误信息。
package main import "fmt" 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 } func main() { res := add(1, 2) fmt.Println(res) // 3 v, ok := exists(map[string]string{"a": "A"}, "a") fmt.Println(v, ok) // A True }
指针
- 主要用途为对传入参数进行修改
-
package main import "fmt" func add2(n int) { n += 2 } func add2ptr(n *int) { *n += 2 } func main() { n := 5 add2(n) fmt.Println(n) // 5 传入函数的参数实际上是一个拷贝,该函数只是对拷贝值+2,没有改变实际变量 add2ptr(&n) fmt.Println(n) // 7 指针指向地址就能真正的改变变量的值 }
结构体
- 结构体是带类型的字段的集合
- 结构体也支持指针
-
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 }
结构体方法
-
实现结构体的两种写法
-
带指针
- 可以对结构体进行修改
-
不带指针
- 实际上进行的是拷贝操作,无法进行修改
-
-
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语言能够很清晰的指导那个函数返回了错误,并且能用简单的if else来处理错误
-
函数实现需要return两个值
- 出现错误可以是return nil和 error
- 没错误就返回原本的结果和nil
-
package main import ( "errors" "fmt" ) 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 } } 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) // wang if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil { fmt.Println(err) // not found return } else { fmt.Println(u.name) } }
字符串操作
- 库函数strings包中有很多常用的字符串工具函数
-
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 }
字符串格式化
- 标准库FMT包中有很多字符串格式相关的方法
- go语言中可以很轻松的用%v来打印任意类型的变量
-
package main import "fmt" 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处理
-
package main import ( "encoding/json" "fmt" ) type userInfo struct { Name string Age int `json:"age"` Hobby []string } func main() { 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"]} buf, err = json.MarshalIndent(a, "", "\t") if err != nil { panic(err) } fmt.Println(string(buf)) var b userInfo err = json.Unmarshal(buf, &b) if err != nil { panic(err) } fmt.Printf("%#v\n", b) // main.userInfo{Name:"wang", Age:18, Hobby:[]string{"Golang", "TypeScript"}} }
时间处理
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
}
数字解析
- 字符串和数字之间的转换
- 使用strconv(string convert)
-
package main import ( "fmt" "strconv" ) func main() { //ParseFloat和ParseInt解析字符串 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) fmt.Println(n) // 4096 //Atoi把十进制字符串转成数字,itoA把数字转成字符串 n2, _ := strconv.Atoi("123") fmt.Println(n2) // 123 //输入不合法的情况 n2, err := strconv.Atoi("AAA") fmt.Println(n2, err) // 0 strconv.Atoi: parsing "AAA": invalid syntax }
进程信息
- 使用os.argv来得到程序执行时指定的命令行参数
-
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 }