Go语言基础上手,告别Java的第一天 | 青训营笔记

128 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记

自我总结

了解了Go的基础语法后,相比Java来说更加自由简单,让我有一种Go是一种弱类型语言的错觉,风格还需要慢慢习惯,练习也需要同步。

Go的主要特点

  • 高性能,高并发
  • 丰富的标准库
  • 完善的工具链
  • 静态链接
  • 快速编译
  • 跨平台
  • 垃圾回收

语法

变量定义的方式

 var a int = 3 // int为可选的
 var b := 3
 ​
 // 常量的定义
 const c string = "abc"
 const d = 3

if

if判断可以先定义然后判断

 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 multiple digits")
 }

循环

Go只有for一种循环

  • 死循环

     for {
         ...
     }
    
  • 普通循环

     for i := 1; i < 3; i++ {
         ...
     }
    

分支

Go中switch语句不需要在每个分支后加上break

  • Go的switch强大到可以在一定程度上代替if

     t := time.Now()
     switch {
         case t.Hour() < 12:
         fmt.Println("It's before noon")
         default:
         fmt.Println("It's after noon")
     }
    

切片

在使用append时,必须把append的结果赋值为原数组:因为slice的原理实际上是它存储了一个长度和一个容量,加一个指向数组的指针,在执行append时,如果容量不够会扩容并返回新的slice

 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]

map

Go的map是完全无序的,遍历的时候不会按照字母顺序,也不会按照插入顺序输出,而是随机顺序

函数

在实际的业务逻辑函数中几乎所有的函数都返回两个值,第一个是真正的返回结果,第二个值是一个错误信息

 func exists(m map[string]string, k string) (v string, ok bool) {
     v, ok = m[v]
     return v, ok
 }

结构体方法

注意带和不带指针的区别

 package main
 ​
 import "fmt"
 ​
 type user struct {
     name     string
     password string
 }
 ​
 // 这里不使用指针实际上操作的是一个copy
 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
 }

错误处理

注意调用函数后处理异常的写法,非常常用

 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)
     }
 }

格式化

注意%v可以匹配任意类型的变量,其中%+v可以打印详细结果,%#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
 }

数字解析

 package main
 ​
 import (
     "fmt"
     "strconv"
 )
 ​
 func main() {
     f, _ := strconv.ParseFloat("1.234", 64)
     fmt.Println(f) // 1.234
 ​
     n, _ := strconv.ParseInt("111", 10, 64) // 第二个形参表示进制,10代表十进制,如果传0表示自动推测,64表示返回一个64精度的整数
     fmt.Println(n)                          // 111
 ​
     n, _ = strconv.ParseInt("0x1000", 0, 64)
     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
 }

\