今天下午才到家,所以今天学习的内容也要少一点点
go
1、走进go语法基础
2、go语言的实战案例
单词
今日学习了20个新单词
运动和娱乐
今日两公里加《巨额来电》
今日知识点
go语言的基础语法和特性
1 什么是go语言
-
高性能,高并发
-
不需要通过其它经过高度优化的第三方库来实现高并发
-
通过go语言的标准库或者基于标准库开发的第三方库即可实现高并发
-
有和c,c++,java媲美的性能
-
-
语法简单,学习曲线平缓,学习周期短,几行代码即可实现一个承载静态文件装载的该并发
package main import( "net/http" ) func main(){ http.Handle("/",http.FileServer(http.Dir("."))) http.ListenAndServe(":8088",nil) }
-
丰富的标准库
-
完善的工具链
-
静态链接
-
快速编译,编译速度非常快
-
跨平台(各种系统,各种奇奇怪怪的小东西)
-
垃圾回收
2 入门
2.1.1 开发环境--安装Golang
打开go的官网,下载后安装提示进行安装即可
2.1.2 配置集成开发环境
可以选择VScode,GoLand
本人选择了vscode进行开发,通过左侧下载go的相关插件即可
2.2 基础语法
Hello World
package main import ( "fmt" ) func main() { fmt.Print("hello world") } // 通过 go run demo.go即可运行 // 编译成二进制文件可以使用go build demo.go ,然后通过./demo运行exe文件
变量
package main import ( "fmt" "math" ) func main() { var a = "initial" var b,c int = 1,2 var d = true var e float64 f := float32(e) g := a + "foo" // 可以通过==去比较字符串 fmt.Println(a,b,c,d,e,f) fmt.Println(g) const s string = "constant" // 常量,没有确定的类型 const h = 500000 const i = 3e20 / h fmt.Println(s,h,math.Sin(h),math.Sin(i)) // 常量最开始没有确定类型,而是根据使用的时候来确定 }
if-esle
package main import ( "fmt" ) func main() { if 7%2 == 0 { fmt.Println("7 is even") } else { fmt.Println("7 is not even") } if 8%4 == 0 { fmt.Println("8 is not even") } if num := 9; num < 0 { fmt.Println(num, "is negative") } else if num < 10 { fmt.Println(num, "has 1 digit") } else { fmt.Println(num, "has mutiple digits") } }
对于if-else,不同于c++,java等,条件里面不需要()
注意:if后面的内容必须重开一行,不能把if里面的东西写在同一行
循环
for j := 7; j < 9; j++ { fmt.Println(j) } for n := 0; n < 5; n++ { if n%2 == 0 { continue } fmt.Println(n) } i := 1 for i <= 3 { fmt.Println(i) i = i + 1 } for { // 死循环 fmt.Println("loop") }
switch
a := 2 switch a { case 1: { fmt.Println("one") } case 4, 5: { fmt.Println("four of five") } default: { fmt.Println("others") } } t := time.Now() switch { case t.Hour() < 12: fmt.Println("before afternoon") default: fmt.Println("after afternon") }
case不需要break,不会进行贯穿,通过case不仅仅可以是数字,还可以是其它的东西
数组和切片
b := [5]int{1,2,3,4,5} var a [5]int a[4] = 100 var twoD [2][3]int func main() { var t [2][3]int for i := 0; i < 2; i++ { for j := 0; j < 3; j++ { t[i][j] = i + j } } fmt.Println(t) // [[0 1 2] [1 2 3]] } s := make([]string, 3) // 切片 s[0] = "a" s[1] = "b" s[2] = "c" fmt.Println("get", s[2]) fmt.Println("len", len(s)) s = append(s, "d") s = append(s, "e", "f") fmt.Println(s) 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里面,其实数组很少使用,因为它长度固定了,通常都是使用切片,因为切片的长度是可以改变的。
切片是一个可变长度的数组,通过make创建一个切片
append必须把原数组的值赋值回去原数组
通过切片具有和python一样的切片操作
map(哈希,字典)
m := make(map[string]int) m["one"] = 1 m["two"] = 2 fmt.Println(len(m)) fmt.Println(m["one"]) // 1 fmt.Println(m["unknow"]) // 0 r, ok := m["unknow"] // ok表示这个map中是否含有这个键 fmt.Println(r, ok) // 0 false m2 := map[string]int{ "one": 1, "two": 2, } delete(m,"one") var m3 = map[string]int{ "one": 1, "two": 2, } fmt.Println(m2, m3) // map[one:1 two:2] map[one:1 two:2]
就是其它语言的哈希,可以通过make进行创建
数据插入map后在map中是无序的
可以通过delete去删除K-V对
range
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) m := map[string]int{ "one": 1, "two": 2, } for k, v := range m { fmt.Println(k, v) } for k := range m { fmt.Println("key", k) }
通过range我们可以对数组,切片,map等进行遍历
对于数组返回两个值,一个值是数组的索引,另一个是该索引下的值
函数
go里面变量类型是后知的,go的函数原生支持返回多个值,第一个值是真正的返回结果,第二个值是错误信息
import "fmt" func add(a int, b int) (int, error) { return a + b, nil } 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) v, ok := exists(map[string]string{"a": "A"}, "a") fmt.Println(v, ok) }
指针
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) add2ptr(&n) fmt.Println(n) }
go语言里面的指针主要用途是对传入的参数进行修改
结构体
结构体是带类型和字段的集合,初始化时可以选择指定或者不指定结构体的内容,使用指针时可以在别的地方对值进行修改
type user struct { name string password string } func main() { a := user{name: "wang", password: "123"} b := user{"wang", "123"} c := user{name: "wang"} c.password = "123" var d user d.name = "wang" d.password = "123" fmt.Println(a, b, c, d) fmt.Println(check2Password(&a, "haha")) fmt.Println(checkPassword(b, "123")) } func checkPassword(u user, password string) bool { return u.password == password } func check2Password(u *user, password string) bool { return u.password == password }
当(u *user)提前后,该方法就从一个普通的方法变为一个结构体方法
func (u *user) resetPassword(password string){ u.password = password }
错误处理
在golang里面,通常使用一个带错误的返回值来对函数进行错误的处理
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", "123"}}, "li") if err != nil { fmt.Println(err) return } fmt.Println(u.name) }
在调用方法的时候,通过判断err是否为空来判断是否发生了错误
字符串操作
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)) }
字符串格式化
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) fmt.Printf("n=%v\n", n) fmt.Printf("p=%v\n", p) fmt.Printf("p=%+v\n", p) fmt.Printf("p=%#v\n", p) f := 3.14159 fmt.Println(f) fmt.Printf("%0.2f\n", f) }
%v可以代替任意类型的变量,%+v可以详细打印,%#v可以更加详细的打印